rearranged some functions (gtk_clist_set_column_auto_resize): new
authorLars Hamann <lars@gtk.org>
Mon, 19 Oct 1998 22:46:38 +0000 (22:46 +0000)
committerLars Hamann <lars@src.gnome.org>
Mon, 19 Oct 1998 22:46:38 +0000 (22:46 +0000)
Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>

* gtk/gtkclist.c: rearranged some functions
(gtk_clist_set_column_auto_resize): new function. toggle auto_resize
  flag of column
(gtk_clist_set_column_resizeable): if resizeable disable auto_resize
(gtk_clist_set_border): deprecated function, use
  gtk_clist_set_shadow_type instead.
(gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
  (adjust_scrollbars): some cleanups
(select_row) (unselect_row): removed. replaced by equivalent
gtk_signal_emit calls
(add_style_data): removed, use gtk_clist_style_set instead
(gtk_clist_style_set): fill in size data, after style was set.
  (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
  (gtk_clist_set_cell_style): auto_resize columns if needed
(column_auto_resize): resize column if needed for auto_resize
(real_clear): disable auto_resize while list destroy
(resize_column): removed

* gtk/gtkctree.c : (gtk_ctree_remove_node)
(gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
(gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
  (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
(real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
(real_tree_collapse) (real_tree_expand) (column_auto_resize):
  auto_resize columns if needed
(gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
(real_clear): disable auto_resize while processing the tree

* gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
for one column

12 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/gtkclist.c
gtk/gtkclist.h
gtk/gtkctree.c
gtk/testgtk.c
tests/testgtk.c

index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 80344ff2a3ce01534f04727255e4bfcec5b8c5cf..dee018fe53bc0453fce486b6cce07732c016061c 100644 (file)
@@ -1,3 +1,36 @@
+Mon Oct 19 23:44:41 1998  Lars Hamann  <lars@gtk.org>
+
+       * gtk/gtkclist.c: rearranged some functions
+       (gtk_clist_set_column_auto_resize): new function. toggle auto_resize
+       flag of column
+       (gtk_clist_set_column_resizeable): if resizeable disable auto_resize 
+       (gtk_clist_set_border): deprecated function, use
+       gtk_clist_set_shadow_type instead.
+       (gtk_clist_set_shadow_type): replacement for gtk_clist_set_border
+       (adjust_scrollbars): some cleanups
+       (select_row) (unselect_row): removed. replaced by equivalent
+       gtk_signal_emit calls
+       (add_style_data): removed, use gtk_clist_style_set instead
+       (gtk_clist_style_set): fill in size data, after style was set. 
+       (set_cell_contents) (gtk_clist_set_shift) (gtk_clist_set_row_style)
+       (gtk_clist_set_cell_style): auto_resize columns if needed
+       (column_auto_resize): resize column if needed for auto_resize 
+       (real_clear): disable auto_resize while list destroy
+       (resize_column): removed
+
+       * gtk/gtkctree.c : (gtk_ctree_remove_node)
+       (gtk_ctree_set_line_style) (gtk_ctree_set_expander_style)
+       (gtk_ctree_node_set_row_style) (gtk_ctree_node_set_cell_style)
+       (set_cell_contents) (gtk_ctree_node_set_shift) (gtk_ctree_set_spacing)
+       (real_tree_move) (gtk_ctree_set_indent) (gtk_ctree_insert_node)
+       (real_tree_collapse) (real_tree_expand) (column_auto_resize):
+       auto_resize columns if needed
+       (gtk_ctree_collapse_recursive) (gtk_ctree_collapse_to_depth)
+       (real_clear): disable auto_resize while processing the tree
+
+       * gtk/testgtk.c (create_clist) (create_ctree): set auto_resize
+       for one column
+
 Mon Oct 19 08:31:36 1998  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkdnd.c (gtk_drag_selection_received): Fixed
index 886174ed8a5b333467b789531b90a00fc7ad94a4..6e048f4ad6f7b8d629c069faf22e7e2acb8dd957 100644 (file)
@@ -143,254 +143,222 @@ enum
   SYNC_INSERT
 };
 
-
-typedef void (*GtkCListSignal1) (GtkObject * object,
-                                gint arg1,
-                                gint arg2,
-                                GdkEvent * arg3,
-                                gpointer data);
-
-typedef void (*GtkCListSignal2) (GtkObject *object,
-                                gpointer data); 
-
-typedef void (*GtkCListSignal3) (GtkObject * object,
-                                gint arg1,
-                                gpointer data);
-typedef void (*GtkCListSignal4) (GtkObject * object,
-                                gint arg1,
-                                gfloat arg2,
-                                gpointer data);
-typedef void (*GtkCListSignal5) (GtkObject * object,
-                                gint arg1,
-                                gfloat arg2,
-                                gboolean arg3,
-                                gpointer data);
-
-
 static void sync_selection (GtkCList * clist,
                            gint row,
                             gint mode);
 
 /* GtkCList Methods */
-static void gtk_clist_class_init (GtkCListClass * klass);
-static void gtk_clist_init (GtkCList * clist);
-static void real_clear (GtkCList * clist);
+static void gtk_clist_class_init (GtkCListClass *klass);
+static void gtk_clist_init       (GtkCList      *clist);
 
 /* GtkObject Methods */
-static void gtk_clist_destroy (GtkObject * object);
-static void gtk_clist_finalize (GtkObject * object);
-
+static void gtk_clist_destroy  (GtkObject *object);
+static void gtk_clist_finalize (GtkObject *object);
 
 /* GtkWidget Methods */
-static void gtk_clist_realize (GtkWidget * widget);
-static void gtk_clist_unrealize (GtkWidget * widget);
-static void gtk_clist_map (GtkWidget * widget);
-static void gtk_clist_unmap (GtkWidget * widget);
-static void gtk_clist_draw (GtkWidget * widget,
-                           GdkRectangle * area);
-static gint gtk_clist_expose (GtkWidget * widget,
-                             GdkEventExpose * event);
-static gint gtk_clist_button_press (GtkWidget * widget,
-                                   GdkEventButton * event);
-static gint gtk_clist_button_release (GtkWidget * widget,
-                                     GdkEventButton * event);
-static gint gtk_clist_motion (GtkWidget * widget, 
-                             GdkEventMotion * event);
-static void gtk_clist_size_request (GtkWidget * widget,
-                                   GtkRequisition * requisition);
-static void gtk_clist_size_allocate (GtkWidget * widget,
-                                    GtkAllocation * allocation);
-static gint get_selection_info (GtkCList * clist,
-                               gint x,
-                               gint y,
-                               gint * row,
-                               gint * column);
+static void gtk_clist_realize         (GtkWidget        *widget);
+static void gtk_clist_unrealize       (GtkWidget        *widget);
+static void gtk_clist_map             (GtkWidget        *widget);
+static void gtk_clist_unmap           (GtkWidget        *widget);
+static void gtk_clist_draw            (GtkWidget        *widget,
+                                      GdkRectangle     *area);
+static gint gtk_clist_expose          (GtkWidget        *widget,
+                                      GdkEventExpose   *event);
+static gint gtk_clist_key_press       (GtkWidget        *widget,
+                                      GdkEventKey      *event);
+static gint gtk_clist_button_press    (GtkWidget        *widget,
+                                      GdkEventButton   *event);
+static gint gtk_clist_button_release  (GtkWidget        *widget,
+                                      GdkEventButton   *event);
+static gint gtk_clist_motion          (GtkWidget        *widget, 
+                                      GdkEventMotion   *event);
+static void gtk_clist_size_request    (GtkWidget        *widget,
+                                      GtkRequisition   *requisition);
+static void gtk_clist_size_allocate   (GtkWidget        *widget,
+                                      GtkAllocation    *allocation);
+static void gtk_clist_draw_focus      (GtkWidget        *widget);
+static gint gtk_clist_focus_in        (GtkWidget        *widget,
+                                      GdkEventFocus    *event);
+static gint gtk_clist_focus_out       (GtkWidget        *widget,
+                                      GdkEventFocus    *event);
+static gint gtk_clist_focus           (GtkContainer     *container,
+                                      GtkDirectionType  direction);
+static void gtk_clist_style_set       (GtkWidget        *widget,
+                                      GtkStyle         *previous_style);
 
 /* GtkContainer Methods */
-static void gtk_clist_forall (GtkContainer *container,
-                             gboolean      include_internals,
-                             GtkCallback   callback,
-                             gpointer      callback_data);
-
-/* Drawing */
-static void get_cell_style (GtkCList     *clist,
-                           GtkCListRow  *clist_row,
-                           gint          state,
-                           gint          column,
-                           GtkStyle    **style,
-                           GdkGC       **fg_gc,
-                           GdkGC       **bg_gc);
-static gint draw_cell_pixmap (GdkWindow    *window,
-                             GdkRectangle *clip_rectangle,
-                             GdkGC        *fg_gc,
-                             GdkPixmap    *pixmap,
-                             GdkBitmap    *mask,
-                             gint          x,
-                             gint          y,
-                             gint          width,
-                             gint          height);
-static void draw_row (GtkCList * clist,
-                     GdkRectangle * area,
-                     gint row,
-                     GtkCListRow * clist_row);
-static void draw_rows (GtkCList * clist,
-                      GdkRectangle * area);
-
-/* Size Allocation */
-static void size_allocate_title_buttons (GtkCList * clist);
-static void size_allocate_columns (GtkCList * clist);
+static void gtk_clist_set_focus_child (GtkContainer  *container,
+                                      GtkWidget     *child);
+static void gtk_clist_forall          (GtkContainer  *container,
+                                      gboolean       include_internals,
+                                      GtkCallback    callback,
+                                      gpointer       callback_data);
 
 /* Selection */
-static void toggle_row (GtkCList * clist,
-                       gint row,
-                       gint column,
-                       GdkEvent * event);
-static void select_row (GtkCList * clist,
-                       gint row,
-                       gint column,
-                       GdkEvent * event);
-static void unselect_row (GtkCList * clist,
-                         gint row,
-                         gint column,
-                         GdkEvent * event);
-static void real_select_row (GtkCList * clist,
-                            gint row,
-                            gint column,
-                            GdkEvent * event);
-static void real_unselect_row (GtkCList * clist,
-                              gint row,
-                              gint column,
-                              GdkEvent * event);
-static void update_extended_selection (GtkCList *clist,
-                                      gint row);
-static GList * selection_find (GtkCList *clist,
-                              gint row_number,
-                              GList *row_list_element);
-static void real_select_all (GtkCList * clist);
-static void real_unselect_all (GtkCList * clist);
-static void move_vertical (GtkCList *clist,
-                          gint row,
-                          gfloat align);
-static void move_horizontal (GtkCList *clist,
-                            gint diff);
-static void real_undo_selection (GtkCList * clist);
-static void fake_unselect_all (GtkCList *clist,
-                              gint row);
-static void fake_toggle_row (GtkCList *clist,
-                            gint row);
-static void resync_selection (GtkCList *clist,
-                             GdkEvent *event);
+static void toggle_row                (GtkCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void real_select_row           (GtkCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void real_unselect_row         (GtkCList      *clist,
+                                      gint           row,
+                                      gint           column,
+                                      GdkEvent      *event);
+static void update_extended_selection (GtkCList      *clist,
+                                      gint           row);
+static GList *selection_find          (GtkCList      *clist,
+                                      gint           row_number,
+                                      GList         *row_list_element);
+static void real_select_all           (GtkCList      *clist);
+static void real_unselect_all         (GtkCList      *clist);
+static void move_vertical             (GtkCList      *clist,
+                                      gint           row,
+                                      gfloat         align);
+static void move_horizontal           (GtkCList      *clist,
+                                      gint           diff);
+static void real_undo_selection       (GtkCList      *clist);
+static void fake_unselect_all         (GtkCList      *clist,
+                                      gint           row);
+static void fake_toggle_row           (GtkCList      *clist,
+                                      gint           row);
+static void resync_selection          (GtkCList      *clist,
+                                      GdkEvent      *event);
+static void sync_selection            (GtkCList      *clist,
+                                      gint           row,
+                                       gint           mode);
+static void set_anchor                (GtkCList      *clist,
+                                      gboolean       add_mode,
+                                      gint           anchor,
+                                      gint           undo_anchor);
+static void start_selection           (GtkCList      *clist);
+static void end_selection             (GtkCList      *clist);
+static void toggle_add_mode           (GtkCList      *clist);
+static void toggle_focus_row          (GtkCList      *clist);
+static void move_focus_row            (GtkCList      *clist,
+                                      GtkScrollType  scroll_type,
+                                      gfloat         position);
+static void scroll_horizontal         (GtkCList      *clist,
+                                      GtkScrollType  scroll_type,
+                                      gfloat         position);
+static void scroll_vertical           (GtkCList      *clist,
+                                      GtkScrollType  scroll_type,
+                                      gfloat         position);
+static void extend_selection          (GtkCList      *clist,
+                                      GtkScrollType  scroll_type,
+                                      gfloat         position,
+                                      gboolean       auto_start_selection);
+static gint get_selection_info        (GtkCList       *clist,
+                                      gint            x,
+                                      gint            y,
+                                      gint           *row,
+                                      gint           *column);
 
 /* Resize Columns */
-static void draw_xor_line (GtkCList * clist);
-static gint new_column_width (GtkCList * clist,
-                             gint column,
-                             gint * x);
-static void real_resize_column (GtkCList * clist,
-                               gint column,
-                               gint width);
-static void resize_column (GtkCList * clist,
-                          gint column,
-                          gint width);
-static void abort_column_resize (GtkCList *clist);
+static void draw_xor_line             (GtkCList       *clist);
+static gint new_column_width          (GtkCList       *clist,
+                                      gint            column,
+                                      gint           *x);
+static void column_auto_resize        (GtkCList       *clist,
+                                      GtkCListRow    *clist_row,
+                                      gint            column,
+                                      gint            old_width);
+static void real_resize_column        (GtkCList       *clist,
+                                      gint            column,
+                                      gint            width);
+static void abort_column_resize       (GtkCList       *clist);
+static void cell_size_request         (GtkCList       *clist,
+                                      GtkCListRow    *clist_row,
+                                      gint            column,
+                                      GtkRequisition *requisition);
 
 /* Buttons */
-static void column_button_create (GtkCList * clist,
-                                 gint column);
-static void column_button_clicked (GtkWidget * widget,
-                                  gpointer data);
+static void column_button_create      (GtkCList       *clist,
+                                      gint            column);
+static void column_button_clicked     (GtkWidget      *widget,
+                                      gpointer        data);
 
 /* Scrollbars */
-static void create_scrollbars (GtkCList * clist);
-static void adjust_scrollbars (GtkCList * clist);
-static void check_exposures   (GtkCList * clist);
-static void vadjustment_changed (GtkAdjustment * adjustment,
-                                gpointer data);
-static void vadjustment_value_changed (GtkAdjustment adjustment,
-                                      gpointer data);
-static void hadjustment_changed (GtkAdjustment * adjustment,
-                                gpointer data);
-static void hadjustment_value_changed (GtkAdjustment adjustment,
-                                      gpointer data);
+static void create_scrollbars         (GtkCList       *clist);
+static void adjust_scrollbars         (GtkCList       *clist);
+static void check_exposures           (GtkCList       *clist);
+static void vadjustment_changed       (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void vadjustment_value_changed (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void hadjustment_changed       (GtkAdjustment  *adjustment,
+                                      gpointer        data);
+static void hadjustment_value_changed (GtkAdjustment  *adjustment,
+                                      gpointer        data);
 
-/* Memory Allocation/Distruction Routines */
-static GtkCListColumn *columns_new (GtkCList * clist);
-
-static void column_title_new (GtkCList    *clist,
-                             gint         column,
-                             const gchar *title);
-static void columns_delete (GtkCList * clist);
-
-static GtkCListRow *row_new (GtkCList * clist);
-
-static void row_delete (GtkCList * clist,
-                       GtkCListRow * clist_row);
-static void set_cell_contents (GtkCList    *clist,
-                              GtkCListRow *clist_row,
-                              gint         column,
-                              GtkCellType  type,
-                              const gchar *text,
-                              guint8       spacing,
-                              GdkPixmap   *pixmap,
-                              GdkBitmap   *mask);
-static gint real_insert_row (GtkCList * clist,
-                            gint row,
-                            gchar * text[]);
-static void real_remove_row (GtkCList * clist,
-                            gint row);
-
-/* Focus handling */
-static void gtk_clist_draw_focus (GtkWidget *widget);
-static gint gtk_clist_focus_in   (GtkWidget     *widget,
-                                 GdkEventFocus *event);
-static gint gtk_clist_focus_out  (GtkWidget     *widget,
-                                 GdkEventFocus *event);
-static gint gtk_clist_focus      (GtkContainer     *container,
-                                 GtkDirectionType  direction);
-static void gtk_clist_set_focus_child (GtkContainer *container,
-                                      GtkWidget    *child);
-static gint gtk_clist_key_press  (GtkWidget   *widget,
-                                 GdkEventKey *event);
-
-/* Selection handling */
-static void set_anchor (GtkCList *clist,
-                       gboolean  add_mode,
-                       gint      anchor,
-                       gint      undo_anchor);
-static void start_selection (GtkCList *clist);
-static void end_selection (GtkCList *clist);
-
-static void toggle_add_mode (GtkCList *clist);
-static void toggle_focus_row (GtkCList *clist);
-static void move_focus_row (GtkCList      *clist,
-                           GtkScrollType  scroll_type,
-                           gfloat         position);
-static void scroll_horizontal (GtkCList      *clist,
-                              GtkScrollType  scroll_type,
-                              gfloat         position);
-static void scroll_vertical (GtkCList      *clist,
-                            GtkScrollType  scroll_type,
-                            gfloat         position);
-static void extend_selection (GtkCList      *clist,
-                             GtkScrollType  scroll_type,
-                             gfloat         position,
-                             gboolean       auto_start_selection);
+/* Drawing */
+static void get_cell_style   (GtkCList      *clist,
+                             GtkCListRow   *clist_row,
+                             gint           state,
+                             gint           column,
+                             GtkStyle     **style,
+                             GdkGC        **fg_gc,
+                             GdkGC        **bg_gc);
+static gint draw_cell_pixmap (GdkWindow     *window,
+                             GdkRectangle  *clip_rectangle,
+                             GdkGC         *fg_gc,
+                             GdkPixmap     *pixmap,
+                             GdkBitmap     *mask,
+                             gint           x,
+                             gint           y,
+                             gint           width,
+                             gint           height);
+static void draw_row         (GtkCList      *clist,
+                             GdkRectangle  *area,
+                             gint           row,
+                             GtkCListRow   *clist_row);
+static void draw_rows        (GtkCList      *clist,
+                             GdkRectangle  *area);
 
-/* Sorting */
-static gint default_compare (GtkCList     *clist,
-                            gconstpointer row1,
-                            gconstpointer row2);
-static GList * gtk_clist_merge (GtkCList *clist,
-                               GList    *a,
-                               GList    *b);
-static GList * gtk_clist_mergesort (GtkCList *clist,
-                                   GList    *list,
-                                   gint      num);
-static void real_sort_list (GtkCList *clist);
+/* Size Allocation */
+static void size_allocate_title_buttons (GtkCList *clist);
+static void size_allocate_columns       (GtkCList *clist);
 
-/* Fill in data after widget is realized and has style */
+/* Memory Allocation/Distruction Routines */
+static GtkCListColumn *columns_new (GtkCList      *clist);
+static void column_title_new       (GtkCList      *clist,
+                                   gint           column,
+                                   const gchar   *title);
+static void columns_delete         (GtkCList      *clist);
+static GtkCListRow *row_new        (GtkCList      *clist);
+static void row_delete             (GtkCList      *clist,
+                                   GtkCListRow   *clist_row);
+static void set_cell_contents      (GtkCList      *clist,
+                                   GtkCListRow   *clist_row,
+                                   gint           column,
+                                   GtkCellType    type,
+                                   const gchar   *text,
+                                   guint8         spacing,
+                                   GdkPixmap     *pixmap,
+                                   GdkBitmap     *mask);
+static gint real_insert_row        (GtkCList      *clist,
+                                   gint           row,
+                                   gchar         *text[]);
+static void real_remove_row        (GtkCList      *clist,
+                                   gint           row);
+static void real_clear             (GtkCList      *clist);
 
-static void add_style_data (GtkCList * clist);
+/* Sorting */
+static gint default_compare        (GtkCList      *clist,
+                                   gconstpointer  row1,
+                                   gconstpointer  row2);
+static void real_sort_list         (GtkCList      *clist);
+static GList *gtk_clist_merge      (GtkCList      *clist,
+                                   GList         *a,
+                                   GList         *b);
+static GList *gtk_clist_mergesort  (GtkCList      *clist,
+                                   GList         *list,
+                                   gint           num);
+/* Misc */
+static gboolean title_focus        (GtkCList      *clist,
+                                   gint           dir);
 
 static GtkContainerClass *parent_class = NULL;
 static guint clist_signals[LAST_SIGNAL] = {0};
@@ -422,7 +390,7 @@ gtk_clist_get_type (void)
 }
 
 static void
-gtk_clist_class_init (GtkCListClass * klass)
+gtk_clist_class_init (GtkCListClass *klass)
 {
   GtkObjectClass *object_class;
   GtkWidgetClass *widget_class;
@@ -566,9 +534,11 @@ gtk_clist_class_init (GtkCListClass * klass)
   widget_class->focus_in_event = gtk_clist_focus_in;
   widget_class->focus_out_event = gtk_clist_focus_out;
   widget_class->draw_focus = gtk_clist_draw_focus;
+  widget_class->style_set = gtk_clist_style_set;
 
   /* container_class->add = NULL; use the default GtkContainerClass warning */
-  /* container_class->remove = NULL; use the default GtkContainerClass warning */
+  /* container_class->remove=NULL; use the default GtkContainerClass warning */
+
   container_class->forall = gtk_clist_forall;
   container_class->focus = gtk_clist_focus;
   container_class->set_focus_child = gtk_clist_set_focus_child;
@@ -597,6 +567,7 @@ gtk_clist_class_init (GtkCListClass * klass)
   klass->end_selection = end_selection;
   klass->abort_column_resize = abort_column_resize;
   klass->set_cell_contents = set_cell_contents;
+  klass->cell_size_request = cell_size_request;
 
   klass->scrollbar_spacing = 5;
 
@@ -802,7 +773,7 @@ gtk_clist_class_init (GtkCListClass * klass)
 }
 
 static void
-gtk_clist_init (GtkCList * clist)
+gtk_clist_init (GtkCList *clist)
 {
   clist->flags = 0;
 
@@ -867,9 +838,9 @@ gtk_clist_init (GtkCList * clist)
 
 /* Constructors */
 void
-gtk_clist_construct (GtkCList * clist,
-                    gint columns,
-                    gchar *titles[])
+gtk_clist_construct (GtkCList *clist,
+                    gint      columns,
+                    gchar    *titles[])
 {
   int i;
 
@@ -885,13 +856,15 @@ gtk_clist_construct (GtkCList * clist,
   if (!clist->row_mem_chunk)
     clist->row_mem_chunk = g_mem_chunk_new ("clist row mem chunk",
                                            sizeof (GtkCListRow),
-                                           sizeof (GtkCListRow) * CLIST_OPTIMUM_SIZE, 
+                                           sizeof (GtkCListRow) *
+                                           CLIST_OPTIMUM_SIZE, 
                                            G_ALLOC_AND_FREE);
 
   if (!clist->cell_mem_chunk)
     clist->cell_mem_chunk = g_mem_chunk_new ("clist cell mem chunk",
                                             sizeof (GtkCell) * columns,
-                                            sizeof (GtkCell) * columns * CLIST_OPTIMUM_SIZE, 
+                                            sizeof (GtkCell) * columns *
+                                            CLIST_OPTIMUM_SIZE, 
                                             G_ALLOC_AND_FREE);
 
   /* set number of columns, allocate memory */
@@ -918,26 +891,16 @@ gtk_clist_construct (GtkCList * clist,
     }
 }
 
-/*
- * GTKCLIST PUBLIC INTERFACE
- *   gtk_clist_new_with_titles
+/* GTKCLIST PUBLIC INTERFACE
  *   gtk_clist_new
+ *   gtk_clist_new_with_titles
+ *   gtk_clist_set_shadow_type
+ *   gtk_clist_set_border *** deprecated function ***
+ *   gtk_clist_set_selection_mode
+ *   gtk_clist_set_policy
+ *   gtk_clist_freeze
+ *   gtk_clist_thaw
  */
-GtkWidget *
-gtk_clist_new_with_titles (gint columns,
-                          gchar * titles[])
-{
-  GtkWidget *widget;
-
-  g_return_val_if_fail (titles != NULL, NULL);
-  
-  widget = gtk_type_new (GTK_TYPE_CLIST);
-  
-  gtk_clist_construct (GTK_CLIST (widget), columns, titles);
-
-  return widget;
-}
-
 GtkWidget *
 gtk_clist_new (gint columns)
 {
@@ -950,23 +913,46 @@ gtk_clist_new (gint columns)
   gtk_clist_construct (clist, columns, NULL);
   return GTK_WIDGET (clist);
 }
+GtkWidget *
+gtk_clist_new_with_titles (gint   columns,
+                          gchar *titles[])
+{
+  GtkWidget *widget;
+
+  g_return_val_if_fail (titles != NULL, NULL);
+  
+  widget = gtk_type_new (GTK_TYPE_CLIST);
+  
+  gtk_clist_construct (GTK_CLIST (widget), columns, titles);
+
+  return widget;
+}
 
 void
-gtk_clist_set_border (GtkCList * clist,
-                     GtkShadowType border)
+gtk_clist_set_shadow_type (GtkCList      *clist,
+                          GtkShadowType  type)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  clist->shadow_type = border;
+  clist->shadow_type = type;
 
   if (GTK_WIDGET_VISIBLE (clist))
     gtk_widget_queue_resize (GTK_WIDGET (clist));
 }
 
+/* deprecated function, use gtk_clist_set_shadow_type instead. */
+void
+gtk_clist_set_border (GtkCList      *clist,
+                     GtkShadowType  border)
+{
+  gtk_clist_set_shadow_type (clist, border);
+}
+
 void
-gtk_clist_set_selection_mode (GtkCList clist,
-                             GtkSelectionMode mode)
+gtk_clist_set_selection_mode (GtkCList         *clist,
+                             GtkSelectionMode  mode)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -998,7 +984,32 @@ gtk_clist_set_selection_mode (GtkCList * clist,
 }
 
 void
-gtk_clist_freeze (GtkCList * clist)
+gtk_clist_set_policy (GtkCList      *clist,
+                     GtkPolicyType  vscrollbar_policy,
+                     GtkPolicyType  hscrollbar_policy)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (clist->vscrollbar_policy != vscrollbar_policy)
+    {
+      clist->vscrollbar_policy = vscrollbar_policy;
+
+      if (GTK_WIDGET (clist)->parent)
+       gtk_widget_queue_resize (GTK_WIDGET (clist));
+    }
+
+  if (clist->hscrollbar_policy != hscrollbar_policy)
+    {
+      clist->hscrollbar_policy = hscrollbar_policy;
+
+      if (GTK_WIDGET (clist)->parent)
+       gtk_widget_queue_resize (GTK_WIDGET (clist));
+    }
+}
+
+void
+gtk_clist_freeze (GtkCList *clist)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1007,7 +1018,7 @@ gtk_clist_freeze (GtkCList * clist)
 }
 
 void
-gtk_clist_thaw (GtkCList * clist)
+gtk_clist_thaw (GtkCList *clist)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1018,8 +1029,26 @@ gtk_clist_thaw (GtkCList * clist)
   draw_rows (clist, NULL);
 }
 
+/* PUBLIC COLUMN FUNCTIONS
+ *   gtk_clist_column_titles_show
+ *   gtk_clist_column_titles_hide
+ *   gtk_clist_column_title_active
+ *   gtk_clist_column_title_passive
+ *   gtk_clist_column_titles_active
+ *   gtk_clist_column_titles_passive
+ *   gtk_clist_set_column_title
+ *   gtk_clist_set_column_widget
+ *   gtk_clist_set_column_justification
+ *   gtk_clist_set_column_visibility
+ *   gtk_clist_set_column_resizeable
+ *   gtk_clist_set_column_auto_resize
+ *   gtk_clist_optimal_column_width
+ *   gtk_clist_set_column_width
+ *   gtk_clist_set_column_min_width
+ *   gtk_clist_set_column_max_width
+ */
 void
-gtk_clist_column_titles_show (GtkCList * clist)
+gtk_clist_column_titles_show (GtkCList *clist)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1034,7 +1063,7 @@ gtk_clist_column_titles_show (GtkCList * clist)
 }
 
 void 
-gtk_clist_column_titles_hide (GtkCList * clist)
+gtk_clist_column_titles_hide (GtkCList *clist)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1049,107 +1078,8 @@ gtk_clist_column_titles_hide (GtkCList * clist)
 }
 
 void
-gtk_clist_set_column_visibility (GtkCList *clist,
-                                gint      column,
-                                gboolean  visible)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (column < 0 || column >= clist->columns)
-    return;
-  if (clist->column[column].visible == visible)
-    return;
-
-  /* don't hide last visible column */
-  if (!visible)
-    {
-      gint i;
-      gint vis_columns = 0;
-
-      for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
-       if (clist->column[i].visible)
-         vis_columns++;
-
-      if (vis_columns < 2)
-       return;
-    }
-
-  clist->column[column].visible = visible;
-  if (visible)
-    gtk_widget_show (clist->column[column].button);
-  else
-    gtk_widget_hide (clist->column[column].button);
-}
-
-void
-gtk_clist_set_column_resizeable (GtkCList *clist,
-                                gint      column,
-                                gint      resizeable)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (column < 0 || column >= clist->columns)
-    return;
-  if (clist->column[column].resizeable == resizeable)
-    return;
-
-  clist->column[column].resizeable = resizeable;
-
-  if (GTK_WIDGET_VISIBLE (clist))
-    size_allocate_title_buttons (clist);
-}
-
-void
-gtk_clist_set_column_min_width (GtkCList *clist,
-                               gint      column,
-                               gint      min_width)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (column < 0 || column >= clist->columns)
-    return;
-  if (clist->column[column].min_width == min_width)
-    return;
-
-  if (clist->column[column].max_width >= 0  &&
-      clist->column[column].max_width < min_width)
-    clist->column[column].min_width = clist->column[column].max_width;
-  else
-    clist->column[column].min_width = min_width;
-
-  if (clist->column[column].area.width < clist->column[column].min_width)
-    gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
-}
-
-void
-gtk_clist_set_column_max_width (GtkCList * clist,
-                               gint column,
-                               gint max_width)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (column < 0 || column >= clist->columns)
-    return;
-  if (clist->column[column].max_width == max_width)
-    return;
-
-  if (clist->column[column].min_width >= 0 && max_width >= 0 &&
-      clist->column[column].min_width > max_width)
-    clist->column[column].max_width = clist->column[column].min_width;
-  else
-    clist->column[column].max_width = max_width;
-  
-  if (clist->column[column].area.width > clist->column[column].max_width)
-    gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
-}
-
-void
-gtk_clist_column_title_active (GtkCList * clist,
-                              gint column)
+gtk_clist_column_title_active (GtkCList *clist,
+                              gint      column)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1168,8 +1098,8 @@ gtk_clist_column_title_active (GtkCList * clist,
 }
 
 void
-gtk_clist_column_title_passive (GtkCList * clist,
-                               gint column)
+gtk_clist_column_title_passive (GtkCList *clist,
+                               gint      column)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
@@ -1180,14 +1110,15 @@ gtk_clist_column_title_passive (GtkCList * clist,
   if (GTK_WIDGET_SENSITIVE (clist->column[column].button) ||
       GTK_WIDGET_CAN_FOCUS (clist->column[column].button))
     {
-      GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_SENSITIVE | GTK_CAN_FOCUS);
+      GTK_WIDGET_UNSET_FLAGS (clist->column[column].button,
+                             GTK_SENSITIVE | GTK_CAN_FOCUS);
       if (GTK_WIDGET_VISIBLE (clist))
        gtk_widget_queue_draw (clist->column[column].button);
     }
 }
 
 void
-gtk_clist_column_titles_active (GtkCList * clist)
+gtk_clist_column_titles_active (GtkCList *clist)
 {
   gint i;
 
@@ -1200,7 +1131,7 @@ gtk_clist_column_titles_active (GtkCList * clist)
 }
 
 void
-gtk_clist_column_titles_passive (GtkCList * clist)
+gtk_clist_column_titles_passive (GtkCList *clist)
 {
   gint i;
 
@@ -1276,9 +1207,9 @@ gtk_clist_set_column_title (GtkCList    *clist,
 }
 
 void
-gtk_clist_set_column_widget (GtkCList clist,
-                            gint column,
-                            GtkWidget * widget)
+gtk_clist_set_column_widget (GtkCList  *clist,
+                            gint       column,
+                            GtkWidget *widget)
 {
   gint new_button = 0;
   GtkWidget *old_widget;
@@ -1318,9 +1249,9 @@ gtk_clist_set_column_widget (GtkCList * clist,
 }
 
 void
-gtk_clist_set_column_justification (GtkCList clist,
-                                   gint column,
-                                   GtkJustification justification)
+gtk_clist_set_column_justification (GtkCList         *clist,
+                                   gint              column,
+                                   GtkJustification  justification)
 {
   GtkWidget *alignment;
 
@@ -1365,436 +1296,594 @@ gtk_clist_set_column_justification (GtkCList * clist,
     draw_rows (clist, NULL);
 }
 
-static void
-real_resize_column (GtkCList * clist,
-                   gint column,
-                   gint width)
+void
+gtk_clist_set_column_visibility (GtkCList *clist,
+                                gint      column,
+                                gboolean  visible)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
   if (column < 0 || column >= clist->columns)
     return;
+  if (clist->column[column].visible == visible)
+    return;
 
-  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
-    width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
-  if (clist->column[column].max_width >= 0 &&
-      width > clist->column[column].max_width)
-    width = clist->column[column].max_width;
-  
-  clist->column[column].width = width;
-  clist->column[column].width_set = TRUE;
+  /* don't hide last visible column */
+  if (!visible)
+    {
+      gint i;
+      gint vis_columns = 0;
 
-  /* FIXME: this is quite expensive to do if the widget hasn't
-   *        been size_allocated yet, and pointless. Should
-   *        a flag be kept
-   */
-  size_allocate_columns (clist);
-  size_allocate_title_buttons (clist);
+      for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
+       if (clist->column[i].visible)
+         vis_columns++;
 
-  if (!GTK_CLIST_FROZEN (clist))
-    {
-      adjust_scrollbars (clist);
-      draw_rows (clist, NULL);
+      if (vis_columns < 2)
+       return;
     }
+
+  clist->column[column].visible = visible;
+  if (visible)
+    gtk_widget_show (clist->column[column].button);
+  else
+    gtk_widget_hide (clist->column[column].button);
 }
 
 void
-gtk_clist_set_column_width (GtkCList * clist,
-                           gint column,
-                           gint width)
+gtk_clist_set_column_resizeable (GtkCList *clist,
+                                gint      column,
+                                gint      resizeable)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
   if (column < 0 || column >= clist->columns)
     return;
+  if (clist->column[column].resizeable == resizeable)
+    return;
 
-  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
-                  column, width);
+  clist->column[column].resizeable = resizeable;
+  if (resizeable)
+    clist->column[column].auto_resize = FALSE;
+
+  if (GTK_WIDGET_VISIBLE (clist))
+    size_allocate_title_buttons (clist);
 }
 
 void
-gtk_clist_set_row_height (GtkCList * clist,
-                         gint height)
+gtk_clist_set_column_auto_resize (GtkCList *clist,
+                                 gint      column,
+                                 gboolean  auto_resize)
 {
-  gint text_height;
-
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (height > 0)
-    clist->row_height = height;
-  else
+  if (column < 0 || column >= clist->columns)
+    return;
+  if (clist->column[column].auto_resize == auto_resize)
     return;
 
-  GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
-  
-  if (GTK_WIDGET_REALIZED (clist))
+  clist->column[column].auto_resize = auto_resize;
+  if (auto_resize)
     {
-      text_height = height - (GTK_WIDGET (clist)->style->font->ascent +
-                             GTK_WIDGET (clist) ->style->font->descent + 1);
-      clist->row_center_offset = ((text_height / 2) + 1.5 +
-                                 GTK_WIDGET (clist)->style->font->ascent);
+      clist->column[column].resizeable = FALSE;
+      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+       {
+         gint width;
+
+         width = gtk_clist_optimal_column_width (clist, column);
+         gtk_clist_set_column_width (clist, column, width);
+       }
     }
-      
-  if (!GTK_CLIST_FROZEN (clist))
+
+  if (GTK_WIDGET_VISIBLE (clist))
+    size_allocate_title_buttons (clist);
+}
+
+gint
+gtk_clist_optimal_column_width (GtkCList *clist,
+                               gint      column)
+{
+  GtkRequisition requisition;
+  GList *list;
+  gint width = 0;
+
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_CLIST (clist), 0);
+
+  if (column < 0 || column > clist->columns)
+    return 0;
+
+  for (list = clist->row_list; list; list = list->next)
     {
-      adjust_scrollbars (clist);
-      draw_rows (clist, NULL);
+      GTK_CLIST_CLASS_FW (clist)->cell_size_request
+       (clist, GTK_CLIST_ROW (list), column, &requisition);
+      width = MAX (width, requisition.width);
     }
+
+  return width;
 }
 
 void
-gtk_clist_moveto (GtkCList * clist,
-                 gint row,
-                 gint column,
-                 gfloat row_align,
-                 gfloat col_align)
+gtk_clist_set_column_width (GtkCList *clist,
+                           gint      column,
+                           gint      width)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < -1 || row >= clist->rows)
-    return;
-  if (column < -1 || column >= clist->columns)
+  if (column < 0 || column >= clist->columns)
     return;
 
-  row_align = CLAMP (row_align, 0, 1);
-  col_align = CLAMP (col_align, 0, 1);
-
-  /* adjust horizontal scrollbar */
-  if (column >= 0)
-    {
-      GtkAdjustment *adj;
-      gint x;
-
-      adj = GTK_RANGE (clist->hscrollbar)->adjustment;
-
-      x = COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
-       (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
-                     CELL_SPACING - clist->column[column].area.width));
-      if (x < 0)
-       gtk_adjustment_set_value (adj, 0.0);
-      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
-       gtk_adjustment_set_value 
-         (adj, LIST_WIDTH (clist) - clist->clist_window_width);
-      else
-       gtk_adjustment_set_value (adj, x);
-    }
-
-  /* adjust vertical scrollbar */
-  if (row >= 0)
-    move_vertical (clist, row, row_align);
+  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
+                  column, width);
 }
 
-GtkCellType 
-gtk_clist_get_cell_type (GtkCList * clist,
-                        gint row,
-                        gint column)
+void
+gtk_clist_set_column_min_width (GtkCList *clist,
+                               gint      column,
+                               gint      min_width)
 {
-  GtkCListRow *clist_row;
-
-  g_return_val_if_fail (clist != NULL, -1);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
-    return -1;
   if (column < 0 || column >= clist->columns)
-    return -1;
+    return;
+  if (clist->column[column].min_width == min_width)
+    return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  if (clist->column[column].max_width >= 0  &&
+      clist->column[column].max_width < min_width)
+    clist->column[column].min_width = clist->column[column].max_width;
+  else
+    clist->column[column].min_width = min_width;
 
-  return clist_row->cell[column].type;
+  if (clist->column[column].area.width < clist->column[column].min_width)
+    gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
 }
 
 void
-gtk_clist_set_text (GtkCList    *clist,
-                   gint         row,
-                   gint         column,
-                   const gchar *text)
+gtk_clist_set_column_max_width (GtkCList *clist,
+                               gint      column,
+                               gint      max_width)
 {
-  GtkCListRow *clist_row;
-
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
-    return;
   if (column < 0 || column >= clist->columns)
     return;
+  if (clist->column[column].max_width == max_width)
+    return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  /* if text is null, then the cell is empty */
-  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
-    (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
-
-  /* redraw the list if it's not frozen */
-  if (!GTK_CLIST_FROZEN (clist))
-    {
-      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
-    }
+  if (clist->column[column].min_width >= 0 && max_width >= 0 &&
+      clist->column[column].min_width > max_width)
+    clist->column[column].max_width = clist->column[column].min_width;
+  else
+    clist->column[column].max_width = max_width;
+  
+  if (clist->column[column].area.width > clist->column[column].max_width)
+    gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
 }
 
-gint
-gtk_clist_get_text (GtkCList * clist,
-                   gint row,
-                   gint column,
-                   gchar ** text)
+/* PRIVATE COLUMN FUNCTIONS
+ *   column_auto_resize
+ *   real_resize_column
+ *   abort_column_resize
+ *   size_allocate_title_buttons
+ *   size_allocate_columns
+ *   new_column_width
+ *   column_button_create
+ *   column_button_clicked
+ */
+static void
+column_auto_resize (GtkCList    *clist,
+                   GtkCListRow *clist_row,
+                   gint         column,
+                   gint         old_width)
 {
-  GtkCListRow *clist_row;
-
-  g_return_val_if_fail (clist != NULL, 0);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
-
-  if (row < 0 || row >= clist->rows)
-    return 0;
-  if (column < 0 || column >= clist->columns)
-    return 0;
+  /* resize column if needed for auto_resize */
+  GtkRequisition requisition;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  if (!clist->column[column].auto_resize ||
+      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    return;
 
-  if (clist_row->cell[column].type != GTK_CELL_TEXT)
-    return 0;
+  GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                column, &requisition);
 
-  if (text)
-    *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
+  if (requisition.width > clist->column[column].width)
+    {
+      if (clist->column[column].max_width < 0)
+       gtk_clist_set_column_width (clist, column, requisition.width);
+      else if (clist->column[column].max_width >
+              clist->column[column].width)
+       gtk_clist_set_column_width (clist, column,
+                                   MIN (requisition.width,
+                                        clist->column[column].max_width));
+    }
+  else if (requisition.width < old_width &&
+          old_width == clist->column[column].width)
+    {
+      GList *list;
+      gint new_width = 0;
 
-  return 1;
+      /* run a "gtk_clist_optimal_column_width" but break, if
+       * the column doesn't shrink */
+      new_width = 0;
+      for (list = clist->row_list; list; list = list->next)
+       {
+         GTK_CLIST_CLASS_FW (clist)->cell_size_request
+           (clist, GTK_CLIST_ROW (list), column, &requisition);
+         new_width = MAX (new_width, requisition.width);
+         if (new_width == clist->column[column].width)
+           break;
+       }
+      if (new_width < clist->column[column].width)
+       gtk_clist_set_column_width
+         (clist, column, MAX (new_width, clist->column[column].min_width));
+    }
 }
 
-void
-gtk_clist_set_pixmap (GtkCList * clist,
-                     gint row,
-                     gint column,
-                     GdkPixmap * pixmap,
-                     GdkBitmap * mask)
+static void
+real_resize_column (GtkCList *clist,
+                   gint      column,
+                   gint      width)
 {
-  GtkCListRow *clist_row;
-
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
-    return;
   if (column < 0 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-  
-  gdk_pixmap_ref (pixmap);
-  
-  if (mask) gdk_pixmap_ref (mask);
+  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+    width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+  if (clist->column[column].max_width >= 0 &&
+      width > clist->column[column].max_width)
+    width = clist->column[column].max_width;
   
-  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
-    (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
+  clist->column[column].width = width;
+  clist->column[column].width_set = TRUE;
+
+  /* FIXME: this is quite expensive to do if the widget hasn't
+   *        been size_allocated yet, and pointless. Should
+   *        a flag be kept
+   */
+  size_allocate_columns (clist);
+  size_allocate_title_buttons (clist);
 
-  /* redraw the list if it's not frozen */
   if (!GTK_CLIST_FROZEN (clist))
     {
-      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+      adjust_scrollbars (clist);
+      draw_rows (clist, NULL);
     }
 }
 
-gint
-gtk_clist_get_pixmap (GtkCList * clist,
-                     gint row,
-                     gint column,
-                     GdkPixmap ** pixmap,
-                     GdkBitmap ** mask)
-{
-  GtkCListRow *clist_row;
-
-  g_return_val_if_fail (clist != NULL, 0);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
-
-  if (row < 0 || row >= clist->rows)
-    return 0;
-  if (column < 0 || column >= clist->columns)
-    return 0;
-
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
-    return 0;
-
-  if (pixmap)
-  {
-    *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
-    /* mask can be NULL */
-    *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
-  }
-
-  return 1;
-}
-
-void
-gtk_clist_set_pixtext (GtkCList    *clist,
-                      gint         row,
-                      gint         column,
-                      const gchar *text,
-                      guint8       spacing,
-                      GdkPixmap   *pixmap,
-                      GdkBitmap   *mask)
+static void
+abort_column_resize (GtkCList *clist)
 {
-  GtkCListRow *clist_row;
-
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
-    return;
-  if (column < 0 || column >= clist->columns)
+  if (!GTK_CLIST_IN_DRAG (clist))
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-  
-  gdk_pixmap_ref (pixmap);
-  if (mask) gdk_pixmap_ref (mask);
-  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
-    (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
+  GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+  gtk_grab_remove (GTK_WIDGET (clist));
+  gdk_pointer_ungrab (GDK_CURRENT_TIME);
+  clist->drag_pos = -1;
 
-  /* redraw the list if it's not frozen */
-  if (!GTK_CLIST_FROZEN (clist))
+  if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
+    draw_xor_line (clist);
+
+  if (GTK_CLIST_ADD_MODE (clist))
     {
-      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
+      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
     }
 }
 
-gint
-gtk_clist_get_pixtext (GtkCList * clist,
-                      gint row,
-                      gint column,
-                      gchar ** text,
-                      guint8 * spacing,
-                      GdkPixmap ** pixmap,
-                      GdkBitmap ** mask)
+static void
+size_allocate_title_buttons (GtkCList *clist)
 {
-  GtkCListRow *clist_row;
+  GtkAllocation button_allocation;
+  gint last_column;
+  gint last_button = 0;
+  gint i;
 
-  g_return_val_if_fail (clist != NULL, 0);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+  if (!GTK_WIDGET_REALIZED (clist))
+    return;
 
-  if (row < 0 || row >= clist->rows)
-    return 0;
-  if (column < 0 || column >= clist->columns)
-    return 0;
+  button_allocation.x = clist->hoffset;
+  button_allocation.y = 0;
+  button_allocation.width = 0;
+  button_allocation.height = clist->column_title_area.height;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  /* find last visible column */
+  for (last_column = clist->columns - 1; last_column >= 0; last_column--)
+    if (clist->column[last_column].visible)
+      break;
 
-  if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
-    return 0;
+  for (i = 0; i < last_column; i++)
+    {
+      if (!clist->column[i].visible)
+       {
+         last_button = i + 1;
+         gdk_window_hide (clist->column[i].window);
+         continue;
+       }
 
-  if (text)
-    *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
-  if (spacing)
-    *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
-  if (pixmap)
-    *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
+      button_allocation.width += (clist->column[i].area.width +
+                                 CELL_SPACING + 2 * COLUMN_INSET);
 
-  /* mask can be NULL */
-  *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
+      if (!clist->column[i + 1].button)
+       {
+         gdk_window_hide (clist->column[i].window);
+         continue;
+       }
 
-  return 1;
+      gtk_widget_size_allocate (clist->column[last_button].button,
+                               &button_allocation);
+      button_allocation.x += button_allocation.width;
+      button_allocation.width = 0;
+
+      if (clist->column[last_button].resizeable)
+       {
+         gdk_window_show (clist->column[last_button].window);
+         gdk_window_move_resize (clist->column[last_button].window,
+                                 button_allocation.x - (DRAG_WIDTH / 2), 
+                                 0, DRAG_WIDTH,
+                                 clist->column_title_area.height);
+       }
+      else
+       gdk_window_hide (clist->column[last_button].window);
+
+      last_button = i + 1;
+    }
+
+  button_allocation.width += (clist->column[last_column].area.width +
+                             2 * (CELL_SPACING + COLUMN_INSET));
+  gtk_widget_size_allocate (clist->column[last_button].button,
+                           &button_allocation);
+
+  if (clist->column[last_button].resizeable)
+    {
+      button_allocation.x += button_allocation.width;
+
+      gdk_window_show (clist->column[last_button].window);
+      gdk_window_move_resize (clist->column[last_button].window,
+                             button_allocation.x - (DRAG_WIDTH / 2), 
+                             0, DRAG_WIDTH, clist->column_title_area.height);
+    }
+  else
+    gdk_window_hide (clist->column[last_button].window);
 }
 
-void
-gtk_clist_set_foreground (GtkCList * clist,
-                         gint row,
-                         GdkColor * color)
+static void
+size_allocate_columns (GtkCList *clist)
 {
-  GtkCListRow *clist_row;
+  gint xoffset = CELL_SPACING + COLUMN_INSET;
+  gint last_column;
+  gint width = 0;
+  gint i;
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  /* find last visible column and calculate correct column width */
+  for (last_column = clist->columns - 1;
+       last_column >= 0 && !clist->column[last_column].visible; last_column--);
 
-  if (row < 0 || row >= clist->rows)
+  if (last_column < 0)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  for (i = 0; i < last_column; i++)
+    {
+      if (!clist->column[i].visible)
+       continue;
+      clist->column[i].area.x = xoffset;
+      clist->column[i].area.width = clist->column[i].width;
+      xoffset += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
+    }
 
-  if (color)
+  if (clist->column[i].width_set)
+    width = clist->column[i].width;
+  else if (clist->column[i].title)
+    width = gdk_string_width (GTK_WIDGET (clist)->style->font,
+                             clist->column[i].title);
+
+  clist->column[i].area.x = xoffset;
+  clist->column[i].area.width = MAX (width,
+                                    clist->clist_window_width - xoffset -
+                                    (CELL_SPACING + COLUMN_INSET));
+}
+
+/* this function returns the new width of the column being resized given
+ * the column and x position of the cursor; the x cursor position is passed
+ * in as a pointer and automagicly corrected if it's beyond min/max limits */
+static gint
+new_column_width (GtkCList *clist,
+                 gint      column,
+                 gint     *x)
+{
+  gint xthickness = GTK_WIDGET (clist)->style->klass->xthickness;
+  gint width;
+  gint cx;
+  gint dx;
+
+  /* first translate the x position from widget->window
+   * to clist->clist_window */
+  cx = *x - xthickness;
+
+  /* calculate new column width making sure it doesn't end up
+   * less than the minimum width */
+  dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
+       (column < clist->columns - 1) * CELL_SPACING);
+  width = cx - dx;
+
+  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
     {
-      clist_row->foreground = *color;
-      clist_row->fg_set = TRUE;
-      if (GTK_WIDGET_REALIZED (clist))
-       gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
-                        &clist_row->foreground);
+      width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
+      cx = dx + width;
+      *x = cx + xthickness;
     }
-  else
-    clist_row->fg_set = FALSE;
+  else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
+          width > clist->column[column].max_width)
+    {
+      width = clist->column[column].max_width;
+      cx = dx + clist->column[column].max_width;
+      *x = cx + xthickness;
+    }      
 
-  if (!GTK_CLIST_FROZEN (clist)
-      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
-    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+  if (cx < 0 || cx > clist->clist_window_width)
+    *x = -1;
+
+  return width;
+}
+
+static void
+column_button_create (GtkCList *clist,
+                     gint      column)
+{
+  GtkWidget *button;
+
+  button = clist->column[column].button = gtk_button_new ();
+  if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
+    gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
+  gtk_widget_set_parent (button, GTK_WIDGET (clist));
+  
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+                     (GtkSignalFunc) column_button_clicked,
+                     (gpointer) clist);
+
+  gtk_widget_show (button);
+}
+
+static void
+column_button_clicked (GtkWidget *widget,
+                      gpointer   data)
+{
+  gint i;
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (data));
+
+  clist = GTK_CLIST (data);
+
+  /* find the column who's button was pressed */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button == widget)
+      break;
+
+  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
 }
 
 void
-gtk_clist_set_background (GtkCList * clist,
-                         gint row,
-                         GdkColor * color)
+gtk_clist_set_row_height (GtkCList *clist,
+                         gint      height)
 {
-  GtkCListRow *clist_row;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (height > 0)
+    clist->row_height = height;
+  else
+    return;
+
+  GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
+  
+  if (GTK_WIDGET_REALIZED (clist))
+    {
+      GdkFont *font;
+      
+      font = GTK_WIDGET (clist)->style->font;
+      clist->row_center_offset = (((height + font->ascent - font->descent - 1)
+                                  / 2) + 1.5);
+    }
+      
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      adjust_scrollbars (clist);
+      draw_rows (clist, NULL);
+    }
+}
 
+void
+gtk_clist_moveto (GtkCList *clist,
+                 gint      row,
+                 gint      column,
+                 gfloat    row_align,
+                 gfloat    col_align)
+{
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
+  if (row < -1 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
     return;
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  row_align = CLAMP (row_align, 0, 1);
+  col_align = CLAMP (col_align, 0, 1);
 
-  if (color)
+  /* adjust horizontal scrollbar */
+  if (column >= 0)
     {
-      clist_row->background = *color;
-      clist_row->bg_set = TRUE;
-      if (GTK_WIDGET_REALIZED (clist))
-       gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
-                        &clist_row->background);
+      GtkAdjustment *adj;
+      gint x;
+
+      adj = GTK_RANGE (clist->hscrollbar)->adjustment;
+
+      x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
+          (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
+                        CELL_SPACING - clist->column[column].area.width)));
+      if (x < 0)
+       gtk_adjustment_set_value (adj, 0.0);
+      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
+       gtk_adjustment_set_value 
+         (adj, LIST_WIDTH (clist) - clist->clist_window_width);
+      else
+       gtk_adjustment_set_value (adj, x);
     }
-  else
-    clist_row->bg_set = FALSE;
 
-  if (!GTK_CLIST_FROZEN (clist)
-      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
-    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+  /* adjust vertical scrollbar */
+  if (row >= 0)
+    move_vertical (clist, row, row_align);
 }
 
-void
-gtk_clist_set_shift (GtkCList * clist,
-                    gint row,
-                    gint column,
-                    gint vertical,
-                    gint horizontal)
+/* PUBLIC CELL FUNCTIONS
+ *   gtk_clist_get_cell_type
+ *   gtk_clist_set_text
+ *   gtk_clist_get_text
+ *   gtk_clist_set_pixmap
+ *   gtk_clist_get_pixmap
+ *   gtk_clist_set_pixtext
+ *   gtk_clist_get_pixtext
+ *   gtk_clist_set_shift
+ */
+GtkCellType 
+gtk_clist_get_cell_type (GtkCList *clist,
+                        gint      row,
+                        gint      column)
 {
   GtkCListRow *clist_row;
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
   if (row < 0 || row >= clist->rows)
-    return;
+    return -1;
   if (column < 0 || column >= clist->columns)
-    return;
+    return -1;
 
   clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  clist_row->cell[column].vertical = vertical;
-  clist_row->cell[column].horizontal = horizontal;
-
-  if (!GTK_CLIST_FROZEN (clist)
-      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
-    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+  return clist_row->cell[column].type;
 }
 
 void
-gtk_clist_set_selectable (GtkCList    *clist,
-                         gint         row,
-                         gboolean     selectable)
+gtk_clist_set_text (GtkCList    *clist,
+                   gint         row,
+                   gint         column,
+                   const gchar *text)
 {
   GtkCListRow *clist_row;
 
@@ -1803,421 +1892,663 @@ gtk_clist_set_selectable (GtkCList    *clist,
 
   if (row < 0 || row >= clist->rows)
     return;
+  if (column < 0 || column >= clist->columns)
+    return;
 
   clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  if (selectable == clist_row->selectable)
-    return;
-
-  clist_row->selectable = selectable;
+  /* if text is null, then the cell is empty */
+  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
 
-  if (!selectable && clist_row->state == GTK_STATE_SELECTED)
+  /* redraw the list if it's not frozen */
+  if (!GTK_CLIST_FROZEN (clist))
     {
-      if (clist->anchor >= 0 &&
-         clist->selection_mode == GTK_SELECTION_EXTENDED)
-       {
-         if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
-           {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (GTK_WIDGET (clist));
-             gdk_pointer_ungrab (GDK_CURRENT_TIME);
-             if (clist->htimer)
-               {
-                 gtk_timeout_remove (clist->htimer);
-                 clist->htimer = 0;
-               }
-             if (clist->vtimer)
-               {
-                 gtk_timeout_remove (clist->vtimer);
-                 clist->vtimer = 0;
-               }
-           }
-         GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
-       }
-      unselect_row (clist, row, -1, NULL);
-    }      
+      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+    }
 }
 
-gboolean
-gtk_clist_get_selectable (GtkCList *clist,
-                         gint      row)
+gint
+gtk_clist_get_text (GtkCList  *clist,
+                   gint       row,
+                   gint       column,
+                   gchar    **text)
 {
-  g_return_val_if_fail (clist != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+  GtkCListRow *clist_row;
+
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
   if (row < 0 || row >= clist->rows)
-    return FALSE;
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
 
-  return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
-}
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-gint
-gtk_clist_prepend (GtkCList *clist,
-                  gchar    *text[])
-{
-  g_return_val_if_fail (clist != NULL, -1);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-  g_return_val_if_fail (text != NULL, -1);
+  if (clist_row->cell[column].type != GTK_CELL_TEXT)
+    return 0;
 
-  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, 0, text);
+  if (text)
+    *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
+
+  return 1;
 }
 
-gint
-gtk_clist_append (GtkCList *clist,
-                 gchar    *text[])
+void
+gtk_clist_set_pixmap (GtkCList  *clist,
+                     gint       row,
+                     gint       column,
+                     GdkPixmap *pixmap,
+                     GdkBitmap *mask)
 {
-  g_return_val_if_fail (clist != NULL, -1);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-  g_return_val_if_fail (text != NULL, -1);
+  GtkCListRow *clist_row;
 
-  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
-}
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-gint
-gtk_clist_insert (GtkCList *clist,
-                 gint      row,
-                 gchar    *text[])
-{
-  g_return_val_if_fail (clist != NULL, -1);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-  g_return_val_if_fail (text != NULL, -1);
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
 
-  if (row < 0 || row > clist->rows)
-    row = clist->rows;
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+  
+  gdk_pixmap_ref (pixmap);
+  
+  if (mask) gdk_pixmap_ref (mask);
+  
+  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
 
-  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
+  /* redraw the list if it's not frozen */
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+    }
 }
 
-static gint
-real_insert_row (GtkCList *clist,
-                gint      row,
-                gchar    *text[])
+gint
+gtk_clist_get_pixmap (GtkCList   *clist,
+                     gint        row,
+                     gint        column,
+                     GdkPixmap **pixmap,
+                     GdkBitmap **mask)
 {
-  gint i;
   GtkCListRow *clist_row;
 
-  g_return_val_if_fail (clist != NULL, -1);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
-  g_return_val_if_fail (text != NULL, -1);
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
-  /* return if out of bounds */
-  if (row < 0 || row > clist->rows)
-    return -1;
+  if (row < 0 || row >= clist->rows)
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
 
-  /* create the row */
-  clist_row = row_new (clist);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  /* set the text in the row's columns */
-  for (i = 0; i < clist->columns; i++)
-    if (text[i])
-      GTK_CLIST_CLASS_FW (clist)->set_cell_contents
-       (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
+  if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
+    return 0;
 
-  if (!clist->rows)
-    {
-      clist->row_list = g_list_append (clist->row_list, clist_row);
-      clist->row_list_end = clist->row_list;
-    }
-  else
-    {
-      if (GTK_CLIST_AUTO_SORT (clist))   /* override insertion pos */
-       {
-         GList *work;
-         
-         row = 0;
-         work = clist->row_list;
-         
-         if (clist->sort_type == GTK_SORT_ASCENDING)
-           {
-             while (row < clist->rows &&
-                    clist->compare (clist, clist_row,
-                                    GTK_CLIST_ROW (work)) > 0)
-               {
-                 row++;
-                 work = work->next;
-               }
-           }
-         else
-           {
-             while (row < clist->rows &&
-                    clist->compare (clist, clist_row,
-                                    GTK_CLIST_ROW (work)) < 0)
-               {
-                 row++;
-                 work = work->next;
-               }
-           }
-       }
-      
-      /* reset the row end pointer if we're inserting at the end of the list */
-      if (row == clist->rows)
-       clist->row_list_end = (g_list_append (clist->row_list_end, clist_row))->next;
-      else
-       clist->row_list = g_list_insert (clist->row_list, clist_row, row);
-    }
-  
-  clist->rows++;
+  if (pixmap)
+  {
+    *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
+    /* mask can be NULL */
+    *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
+  }
 
-  if (row < ROW_FROM_YPIXEL (clist, 0))
-    clist->voffset -= (clist->row_height + CELL_SPACING);
+  return 1;
+}
 
-  /* syncronize the selection list */
-  sync_selection (clist, row, SYNC_INSERT);
+void
+gtk_clist_set_pixtext (GtkCList    *clist,
+                      gint         row,
+                      gint         column,
+                      const gchar *text,
+                      guint8       spacing,
+                      GdkPixmap   *pixmap,
+                      GdkBitmap   *mask)
+{
+  GtkCListRow *clist_row;
 
-  /* redraw the list if it isn't frozen */
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+  
+  gdk_pixmap_ref (pixmap);
+  if (mask) gdk_pixmap_ref (mask);
+  GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+    (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
+
+  /* redraw the list if it's not frozen */
   if (!GTK_CLIST_FROZEN (clist))
     {
-      adjust_scrollbars (clist);
-
       if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       draw_rows (clist, NULL);
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
     }
-
-  return row;
 }
 
-void
-gtk_clist_remove (GtkCList * clist,
-                 gint row)
+gint
+gtk_clist_get_pixtext (GtkCList   *clist,
+                      gint        row,
+                      gint        column,
+                      gchar     **text,
+                      guint8     *spacing,
+                      GdkPixmap **pixmap,
+                      GdkBitmap **mask)
 {
-  GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
+  GtkCListRow *clist_row;
+
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+
+  if (row < 0 || row >= clist->rows)
+    return 0;
+  if (column < 0 || column >= clist->columns)
+    return 0;
+
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+
+  if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
+    return 0;
+
+  if (text)
+    *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
+  if (spacing)
+    *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
+  if (pixmap)
+    *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
+
+  /* mask can be NULL */
+  *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
+
+  return 1;
 }
 
-static void
-real_remove_row (GtkCList * clist,
-                gint row)
+void
+gtk_clist_set_shift (GtkCList *clist,
+                    gint      row,
+                    gint      column,
+                    gint      vertical,
+                    gint      horizontal)
 {
-  gint was_visible, was_selected;
-  GList *list;
+  GtkRequisition requisition;
   GtkCListRow *clist_row;
 
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  /* return if out of bounds */
-  if (row < 0 || row > (clist->rows - 1))
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
     return;
 
-  was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
-  was_selected = 0;
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  /* get the row we're going to delete */
-  list = g_list_nth (clist->row_list, row);
-  clist_row = list->data;
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
 
-  /* if we're removing a selected row, we have to make sure
-   * it's properly unselected, and then sync up the clist->selected
-   * list to reflect the deincrimented indexies of rows after the
-   * removal */
-  if (clist_row->state == GTK_STATE_SELECTED)
-    {
-      switch (clist->selection_mode)
-       {
-       case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
-       case GTK_SELECTION_EXTENDED:
-         unselect_row (clist, row, -1, NULL);
-         break;
-
-       case GTK_SELECTION_BROWSE:
-         select_row (clist, row - 1, -1, NULL);
-         break;
+  clist_row->cell[column].vertical = vertical;
+  clist_row->cell[column].horizontal = horizontal;
 
-       default:
-         break;
-       }
-    }
+  column_auto_resize (clist, clist_row, column, requisition.width);
 
-  /* reset the row end pointer if we're removing at the
-   * end of the list */
-  if (row == clist->rows - 1)
-    clist->row_list_end = list->prev;
-  if (row >= clist->focus_row && clist->focus_row >=0)
-    clist->focus_row--;
+  if (!GTK_CLIST_FROZEN (clist)
+      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+}
 
-  clist->row_list = g_list_remove (clist->row_list, clist_row);
-  clist->rows--;
-  
-  if (row < ROW_FROM_YPIXEL (clist, 0))
-    clist->voffset += clist->row_height + CELL_SPACING;
+/* PRIVATE CELL FUNCTIONS
+ *   set_cell_contents
+ *   cell_size_request
+ */
+static void
+set_cell_contents (GtkCList    *clist,
+                  GtkCListRow *clist_row,
+                  gint         column,
+                  GtkCellType  type,
+                  const gchar *text,
+                  guint8       spacing,
+                  GdkPixmap   *pixmap,
+                  GdkBitmap   *mask)
+{
+  GtkRequisition requisition;
 
-  sync_selection (clist, row, SYNC_REMOVE);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_if_fail (clist_row != NULL);
 
-  /* toast the row */
-  row_delete (clist, clist_row);
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
 
-  /* redraw the row if it isn't frozen */
-  if (!GTK_CLIST_FROZEN (clist))
+  switch (clist_row->cell[column].type)
     {
-      adjust_scrollbars (clist);
-
-      if (was_visible)
-       draw_rows (clist, NULL);
+    case GTK_CELL_EMPTY:
+      break;
+    case GTK_CELL_TEXT:
+      g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
+      break;
+    case GTK_CELL_PIXMAP:
+      gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
+      if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
+       gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
+      break;
+    case GTK_CELL_PIXTEXT:
+      g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
+      gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
+      if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
+       gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
+      break;
+    case GTK_CELL_WIDGET:
+      /* unimplimented */
+      break;
+    default:
+      break;
     }
-}
 
-static void
-sync_selection (GtkCList * clist,
-               gint row,
-               gint mode)
-{
-  GList *list;
-  gint d;
+  clist_row->cell[column].type = GTK_CELL_EMPTY;
 
-  if (mode == SYNC_INSERT)
-    d = 1;
-  else
-    d = -1;
-      
-  if (clist->focus_row >= row)
+  switch (type)
     {
-      clist->focus_row += d;
-      if (clist->focus_row == -1 && clist->rows >= 1)
-       clist->focus_row = 0;
+    case GTK_CELL_TEXT:
+      if (text)
+       {
+         clist_row->cell[column].type = GTK_CELL_TEXT;
+         GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
+       }
+      break;
+    case GTK_CELL_PIXMAP:
+      if (pixmap)
+       {
+         clist_row->cell[column].type = GTK_CELL_PIXMAP;
+         GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
+         /* We set the mask even if it is NULL */
+         GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    case GTK_CELL_PIXTEXT:
+      if (text && pixmap)
+       {
+         clist_row->cell[column].type = GTK_CELL_PIXTEXT;
+         GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
+         GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
+         GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
+         GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+       }
+      break;
+    default:
+      break;
     }
 
-  if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
-    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+  column_auto_resize (clist, clist_row, column, requisition.width);
+}
 
-  g_list_free (clist->undo_selection);
-  g_list_free (clist->undo_unselection);
-  clist->undo_selection = NULL;
-  clist->undo_unselection = NULL;
+static void
+cell_size_request (GtkCList       *clist,
+                  GtkCListRow    *clist_row,
+                  gint            column,
+                  GtkRequisition *requisition)
+{
+  GtkStyle *style;
+  gint width;
+  gint height;
 
-  clist->anchor = -1;
-  clist->drag_pos = -1;
-  clist->undo_anchor = clist->focus_row;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_if_fail (requisition != NULL);
 
-  list = clist->selection;
-  while (list)
+  get_cell_style (clist, clist_row, GTK_STATE_PRELIGHT, column, &style,
+                 NULL, NULL);
+
+  switch (clist_row->cell[column].type)
     {
-      if (GPOINTER_TO_INT (list->data) >= row)
-       list->data = ((gchar*) list->data) + d;
-      list = list->next;
+    case GTK_CELL_TEXT:
+      requisition->width =
+       gdk_string_width (style->font,
+                         GTK_CELL_TEXT (clist_row->cell[column])->text);
+      requisition->height = style->font->ascent + style->font->descent;
+      break;
+    case GTK_CELL_PIXTEXT:
+      gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width = width +
+       GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing +
+       gdk_string_width (style->font,
+                         GTK_CELL_TEXT (clist_row->cell[column])->text);
+
+      requisition->height = MAX (style->font->ascent + style->font->descent,
+                                height);
+      break;
+    case GTK_CELL_PIXMAP:
+      gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width = width;
+      requisition->height = height;
+      break;
+    default:
+      requisition->width  = 0;
+      requisition->height = 0;
+      break;
     }
+
+  requisition->width  += clist_row->cell[column].horizontal;
+  requisition->height += clist_row->cell[column].vertical;
 }
 
-void
-gtk_clist_clear (GtkCList * clist)
+/* PUBLIC INSERT/REMOVE ROW FUNCTIONS
+ *   gtk_clist_prepend
+ *   gtk_clist_append
+ *   gtk_clist_insert
+ *   gtk_clist_remove
+ *   gtk_clist_clear
+ */
+gint
+gtk_clist_prepend (GtkCList *clist,
+                  gchar    *text[])
 {
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-  
-  GTK_CLIST_CLASS_FW (clist)->clear (clist);
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
+
+  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, 0, text);
 }
 
-static void
-real_clear (GtkCList * clist)
+gint
+gtk_clist_append (GtkCList *clist,
+                 gchar    *text[])
 {
-  GList *list, *free_list;
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, clist->rows, text);
+}
 
-  /* free up the selection list */
-  g_list_free (clist->selection);
-  g_list_free (clist->undo_selection);
-  g_list_free (clist->undo_unselection);
+gint
+gtk_clist_insert (GtkCList *clist,
+                 gint      row,
+                 gchar    *text[])
+{
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
 
-  clist->selection = NULL;
-  clist->selection_end = NULL;
-  clist->undo_selection = NULL;
-  clist->undo_unselection = NULL;
-  clist->voffset = 0;
-  clist->focus_row = -1;
-  clist->anchor = -1;
-  clist->undo_anchor = -1;
-  clist->anchor_state = GTK_STATE_SELECTED;
-  clist->drag_pos = -1;
+  if (row < 0 || row > clist->rows)
+    row = clist->rows;
 
-  /* remove all the rows */
-  free_list = clist->row_list;
-  clist->row_list = NULL;
-  clist->row_list_end = NULL;
-  clist->rows = 0;
-  for (list = free_list; list; list = list->next)
-    row_delete (clist, GTK_CLIST_ROW (list));
-  g_list_free (free_list);
+  return GTK_CLIST_CLASS_FW (clist)->insert_row (clist, row, text);
+}
 
-  /* zero-out the scrollbars */
-  if (clist->vscrollbar)
-    {
-      GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
-      gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
-      
-      if (!GTK_CLIST_FROZEN (clist))
-       gtk_clist_thaw (clist);
-    }
+void
+gtk_clist_remove (GtkCList *clist,
+                 gint      row)
+{
+  GTK_CLIST_CLASS_FW (clist)->remove_row (clist, row);
 }
 
-void 
-gtk_clist_swap_rows (GtkCList * clist,
-                    gint row1, 
-                    gint row2)
+void
+gtk_clist_clear (GtkCList *clist)
 {
-  gint first, last;
-  GList *list, *link1, *link2;
-  gpointer swap;
-  
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  GTK_CLIST_CLASS_FW (clist)->clear (clist);
+}
 
-  if (GTK_CLIST_AUTO_SORT (clist))
-    return;
+/* PRIVATE INSERT/REMOVE ROW FUNCTIONS
+ *   real_insert_row
+ *   real_remove_row
+ *   real_clear
+ *   sync_selection
+ */
+static gint
+real_insert_row (GtkCList *clist,
+                gint      row,
+                gchar    *text[])
+{
+  gint i;
+  GtkCListRow *clist_row;
 
-  if (row1 < 0 || row1 > (clist->rows - 1))
-    return;
+  g_return_val_if_fail (clist != NULL, -1);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
+  g_return_val_if_fail (text != NULL, -1);
 
-  if (row2 < 0 || row2 > (clist->rows - 1))
-    return;
+  /* return if out of bounds */
+  if (row < 0 || row > clist->rows)
+    return -1;
 
-  first = MIN (row1, row2);
-  last = MAX (row1, row2);
+  /* create the row */
+  clist_row = row_new (clist);
 
-  link1 = g_list_nth (clist->row_list, first);
-  link2 = g_list_nth (link1, row2 - row1);
+  /* set the text in the row's columns */
+  for (i = 0; i < clist->columns; i++)
+    if (text[i])
+      GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+       (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
 
-  swap = link1->data;
-  link1->data = link2->data;
-  link2->data = swap;
-  
-  list = clist->selection;
-  while (list)
+  if (!clist->rows)
     {
-      if (GPOINTER_TO_INT (list->data) == row1)
-       list->data = GINT_TO_POINTER (row2);
-      
-      if (GPOINTER_TO_INT (list->data) == row2)
-       list->data = GINT_TO_POINTER (row1);
+      clist->row_list = g_list_append (clist->row_list, clist_row);
+      clist->row_list_end = clist->row_list;
+    }
+  else
+    {
+      if (GTK_CLIST_AUTO_SORT (clist))   /* override insertion pos */
+       {
+         GList *work;
+         
+         row = 0;
+         work = clist->row_list;
+         
+         if (clist->sort_type == GTK_SORT_ASCENDING)
+           {
+             while (row < clist->rows &&
+                    clist->compare (clist, clist_row,
+                                    GTK_CLIST_ROW (work)) > 0)
+               {
+                 row++;
+                 work = work->next;
+               }
+           }
+         else
+           {
+             while (row < clist->rows &&
+                    clist->compare (clist, clist_row,
+                                    GTK_CLIST_ROW (work)) < 0)
+               {
+                 row++;
+                 work = work->next;
+               }
+           }
+       }
       
-      list = list->next;
+      /* reset the row end pointer if we're inserting at the end of the list */
+      if (row == clist->rows)
+       clist->row_list_end = (g_list_append (clist->row_list_end,
+                                             clist_row))->next;
+      else
+       clist->row_list = g_list_insert (clist->row_list, clist_row, row);
     }
   
+  clist->rows++;
+
+  if (row < ROW_FROM_YPIXEL (clist, 0))
+    clist->voffset -= (clist->row_height + CELL_SPACING);
+
+  /* syncronize the selection list */
+  sync_selection (clist, row, SYNC_INSERT);
+
+  /* redraw the list if it isn't frozen */
   if (!GTK_CLIST_FROZEN (clist))
     {
-      if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row
-         (clist, NULL, row1, GTK_CLIST_ROW (link2));
+      adjust_scrollbars (clist);
 
-      if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row
-         (clist, NULL, row2, GTK_CLIST_ROW (link1));
+      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       draw_rows (clist, NULL);
+    }
+
+  return row;
+}
+
+static void
+real_remove_row (GtkCList *clist,
+                gint      row)
+{
+  gint was_visible, was_selected;
+  GList *list;
+  GtkCListRow *clist_row;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  /* return if out of bounds */
+  if (row < 0 || row > (clist->rows - 1))
+    return;
+
+  was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
+  was_selected = 0;
+
+  /* get the row we're going to delete */
+  list = g_list_nth (clist->row_list, row);
+  clist_row = list->data;
+
+  /* if we're removing a selected row, we have to make sure
+   * it's properly unselected, and then sync up the clist->selected
+   * list to reflect the deincrimented indexies of rows after the
+   * removal */
+  if (clist_row->state == GTK_STATE_SELECTED)
+    {
+      switch (clist->selection_mode)
+       {
+       case GTK_SELECTION_SINGLE:
+       case GTK_SELECTION_MULTIPLE:
+       case GTK_SELECTION_EXTENDED:
+         gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+                          row, -1, NULL);
+         break;
+       case GTK_SELECTION_BROWSE:
+         gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                          row - 1, -1, NULL);
+         break;
+       default:
+         break;
+       }
+    }
+
+  /* reset the row end pointer if we're removing at the
+   * end of the list */
+  if (row == clist->rows - 1)
+    clist->row_list_end = list->prev;
+  if (row >= clist->focus_row && clist->focus_row >=0)
+    clist->focus_row--;
+
+  clist->row_list = g_list_remove (clist->row_list, clist_row);
+  clist->rows--;
+  
+  if (row < ROW_FROM_YPIXEL (clist, 0))
+    clist->voffset += clist->row_height + CELL_SPACING;
+
+  sync_selection (clist, row, SYNC_REMOVE);
+
+  /* toast the row */
+  row_delete (clist, clist_row);
+
+  /* redraw the row if it isn't frozen */
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      adjust_scrollbars (clist);
+
+      if (was_visible)
+       draw_rows (clist, NULL);
+    }
+}
+
+static void
+real_clear (GtkCList *clist)
+{
+  GList *list;
+  GList *free_list;
+  gint i;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  /* free up the selection list */
+  g_list_free (clist->selection);
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
+  clist->voffset = 0;
+  clist->focus_row = -1;
+  clist->anchor = -1;
+  clist->undo_anchor = -1;
+  clist->anchor_state = GTK_STATE_SELECTED;
+  clist->drag_pos = -1;
+
+  /* remove all the rows */
+  GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
+  free_list = clist->row_list;
+  clist->row_list = NULL;
+  clist->row_list_end = NULL;
+  clist->rows = 0;
+  for (list = free_list; list; list = list->next)
+    row_delete (clist, GTK_CLIST_ROW (list));
+  g_list_free (free_list);
+  GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize && clist->column[i].width > 0)
+      gtk_clist_set_column_width (clist, i, 0);
+
+  /* zero-out the scrollbars */
+  if (clist->vscrollbar)
+    {
+      GTK_RANGE (clist->vscrollbar)->adjustment->value = 0.0;
+      gtk_signal_emit_by_name
+       (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
+      if (!GTK_CLIST_FROZEN (clist))
+       gtk_clist_thaw (clist);
     }
 }
 
+/* PUBLIC ROW FUNCTIONS
+ *   gtk_clist_set_row_data
+ *   gtk_clist_set_row_data_full
+ *   gtk_clist_get_row_data
+ *   gtk_clist_find_row_from_data
+ *   gtk_clist_swap_rows
+ *   gtk_clist_row_is_visible
+ *   gtk_clist_set_foreground
+ *   gtk_clist_set_background
+ */
 void
-gtk_clist_set_row_data (GtkCList * clist,
-                       gint row,
-                       gpointer data)
+gtk_clist_set_row_data (GtkCList *clist,
+                       gint      row,
+                       gpointer  data)
 {
   gtk_clist_set_row_data_full (clist, row, data, NULL);
 }
 
 void
-gtk_clist_set_row_data_full (GtkCList clist,
-                            gint row,
-                            gpointer data,
-                            GtkDestroyNotify destroy)
+gtk_clist_set_row_data_full (GtkCList         *clist,
+                            gint              row,
+                            gpointer          data,
+                            GtkDestroyNotify  destroy)
 {
   GtkCListRow *clist_row;
 
@@ -2233,8 +2564,8 @@ gtk_clist_set_row_data_full (GtkCList * clist,
 }
 
 gpointer
-gtk_clist_get_row_data (GtkCList * clist,
-                       gint row)
+gtk_clist_get_row_data (GtkCList *clist,
+                       gint      row)
 {
   GtkCListRow *clist_row;
 
@@ -2249,8 +2580,8 @@ gtk_clist_get_row_data (GtkCList * clist,
 }
 
 gint
-gtk_clist_find_row_from_data (GtkCList * clist,
-                             gpointer data)
+gtk_clist_find_row_from_data (GtkCList *clist,
+                             gpointer  data)
 {
   GList *list;
   gint n;
@@ -2258,9 +2589,6 @@ gtk_clist_find_row_from_data (GtkCList * clist,
   g_return_val_if_fail (clist != NULL, -1);
   g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
-  if (clist->rows < 1)
-    return -1; /* is this an optimization or just worthless? */
-
   for (n = 0, list = clist->row_list; list; n++, list = list->next)
     if (GTK_CLIST_ROW (list)->data == data)
       return n;
@@ -2268,43 +2596,64 @@ gtk_clist_find_row_from_data (GtkCList * clist,
   return -1;
 }
 
-void
-gtk_clist_select_row (GtkCList * clist,
-                     gint row,
-                     gint column)
+void 
+gtk_clist_swap_rows (GtkCList *clist,
+                    gint      row1, 
+                    gint      row2)
 {
+  gint first, last;
+  GList *list, *link1, *link2;
+  gpointer swap;
+  
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (row < 0 || row >= clist->rows)
+  if (GTK_CLIST_AUTO_SORT (clist))
     return;
 
-  if (column < -1 || column >= clist->columns)
+  if (row1 < 0 || row1 > (clist->rows - 1))
     return;
 
-  select_row (clist, row, column, NULL);
-}
+  if (row2 < 0 || row2 > (clist->rows - 1))
+    return;
 
-void
-gtk_clist_unselect_row (GtkCList * clist,
-                       gint row,
-                       gint column)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  first = MIN (row1, row2);
+  last = MAX (row1, row2);
 
-  if (row < 0 || row >= clist->rows)
-    return;
+  link1 = g_list_nth (clist->row_list, first);
+  link2 = g_list_nth (link1, row2 - row1);
 
-  if (column < -1 || column >= clist->columns)
-    return;
+  swap = link1->data;
+  link1->data = link2->data;
+  link2->data = swap;
+  
+  list = clist->selection;
+  while (list)
+    {
+      if (GPOINTER_TO_INT (list->data) == row1)
+       list->data = GINT_TO_POINTER (row2);
+      
+      if (GPOINTER_TO_INT (list->data) == row2)
+       list->data = GINT_TO_POINTER (row1);
+      
+      list = list->next;
+    }
+  
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      if (gtk_clist_row_is_visible (clist, row1) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row
+         (clist, NULL, row1, GTK_CLIST_ROW (link2));
 
-  unselect_row (clist, row, column, NULL);
+      if (gtk_clist_row_is_visible (clist, row2) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row
+         (clist, NULL, row2, GTK_CLIST_ROW (link1));
+    }
 }
 
 GtkVisibility
-gtk_clist_row_is_visible (GtkCList * clist,
-                         gint row)
+gtk_clist_row_is_visible (GtkCList *clist,
+                         gint      row)
 {
   gint top;
 
@@ -2332,3607 +2681,3756 @@ gtk_clist_row_is_visible (GtkCList * clist,
   return GTK_VISIBILITY_FULL;
 }
 
-#if 0
-static GtkAdjustment*
-gtk_clist_get_vadjustment (GtkCList * clist)
-{
-  g_return_val_if_fail (clist != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
-
-  return gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
-}
-
-static GtkAdjustment*
-gtk_clist_get_hadjustment (GtkCList * clist)
-{
-  g_return_val_if_fail (clist != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
-
-  return gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
-}
-#endif
-
 void
-gtk_clist_set_policy (GtkCList * clist,
-                     GtkPolicyType vscrollbar_policy,
-                     GtkPolicyType hscrollbar_policy)
+gtk_clist_set_foreground (GtkCList *clist,
+                         gint      row,
+                         GdkColor *color)
 {
+  GtkCListRow *clist_row;
+
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (clist->vscrollbar_policy != vscrollbar_policy)
-    {
-      clist->vscrollbar_policy = vscrollbar_policy;
+  if (row < 0 || row >= clist->rows)
+    return;
 
-      if (GTK_WIDGET (clist)->parent)
-       gtk_widget_queue_resize (GTK_WIDGET (clist));
-    }
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  if (clist->hscrollbar_policy != hscrollbar_policy)
+  if (color)
     {
-      clist->hscrollbar_policy = hscrollbar_policy;
-
-      if (GTK_WIDGET (clist)->parent)
-       gtk_widget_queue_resize (GTK_WIDGET (clist));
+      clist_row->foreground = *color;
+      clist_row->fg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (clist))
+       gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+                        &clist_row->foreground);
     }
+  else
+    clist_row->fg_set = FALSE;
+
+  if (!GTK_CLIST_FROZEN (clist)
+      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
 }
 
 void
-gtk_clist_undo_selection (GtkCList *clist)
+gtk_clist_set_background (GtkCList *clist,
+                         gint      row,
+                         GdkColor *color)
 {
+  GtkCListRow *clist_row;
+
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
-      (clist->undo_selection || clist->undo_unselection))
-    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
+  if (row < 0 || row >= clist->rows)
+    return;
+
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+
+  if (color)
+    {
+      clist_row->background = *color;
+      clist_row->bg_set = TRUE;
+      if (GTK_WIDGET_REALIZED (clist))
+       gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
+                        &clist_row->background);
+    }
+  else
+    clist_row->bg_set = FALSE;
+
+  if (!GTK_CLIST_FROZEN (clist)
+      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
 }
 
-static void
-real_undo_selection (GtkCList *clist)
+/* PUBLIC ROW/CELL STYLE FUNCTIONS
+ *   gtk_clist_set_cell_style
+ *   gtk_clist_get_cell_style
+ *   gtk_clist_set_row_style
+ *   gtk_clist_get_row_style
+ */
+void
+gtk_clist_set_cell_style (GtkCList *clist,
+                         gint      row,
+                         gint      column,
+                         GtkStyle *style)
 {
-  GList *work;
+  GtkRequisition requisition;
+  GtkCListRow *clist_row;
 
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
-      clist->selection_mode != GTK_SELECTION_EXTENDED)
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < 0 || column >= clist->columns)
     return;
 
-  if (clist->anchor >= 0)
-    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  if (!(clist->undo_selection || clist->undo_unselection))
+  if (clist_row->cell[column].style == style)
+    return;
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                  column, &requisition);
+
+  if (clist_row->cell[column].style)
     {
-      gtk_clist_unselect_all (clist);
-      return;
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->cell[column].style);
+      gtk_style_unref (clist_row->cell[column].style);
     }
 
-  for (work = clist->undo_selection; work; work = work->next)
-    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                    GPOINTER_TO_INT (work->data), -1, NULL);
+  clist_row->cell[column].style = style;
 
-  for (work = clist->undo_unselection; work; work = work->next)
-    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
-                    GPOINTER_TO_INT (work->data), -1, NULL);
+  if (clist_row->cell[column].style)
+    {
+      gtk_style_ref (clist_row->cell[column].style);
+      
+      if (GTK_WIDGET_REALIZED (clist))
+        clist_row->cell[column].style =
+         gtk_style_attach (clist_row->cell[column].style,
+                           clist->clist_window);
+    }
 
-  if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+  column_auto_resize (clist, clist_row, column, requisition.width);
+
+  /* redraw the list if it's not frozen */
+  if (!GTK_CLIST_FROZEN (clist))
     {
-      gtk_clist_draw_focus (GTK_WIDGET (clist));
-      clist->focus_row = clist->undo_anchor;
-      gtk_clist_draw_focus (GTK_WIDGET (clist));
+      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
     }
-  else
-    clist->focus_row = clist->undo_anchor;
-  
-  clist->undo_anchor = -1;
-  g_list_free (clist->undo_selection);
-  g_list_free (clist->undo_unselection);
-  clist->undo_selection = NULL;
-  clist->undo_unselection = NULL;
+}
 
-  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
-      clist->clist_window_height)
-    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
-    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+GtkStyle *
+gtk_clist_get_cell_style (GtkCList *clist,
+                         gint      row,
+                         gint      column)
+{
+  GtkCListRow *clist_row;
+
+  g_return_val_if_fail (clist != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
+
+  if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
+    return NULL;
+
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+
+  return clist_row->cell[column].style;
 }
 
-/*
- * GTKOBJECT
- *   gtk_clist_destroy
- *   gtk_clist_finalize
- */
-static void
-gtk_clist_destroy (GtkObject * object)
+void
+gtk_clist_set_row_style (GtkCList *clist,
+                        gint      row,
+                        GtkStyle *style)
 {
+  GtkRequisition requisition;
+  GtkCListRow *clist_row;
+  gint *old_width;
   gint i;
-  GtkCList *clist;
 
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_CLIST (object));
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  clist = GTK_CLIST (object);
+  if (row < 0 || row >= clist->rows)
+    return;
 
-  /* freeze the list */
-  GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  /* get rid of all the rows */
-  gtk_clist_clear (clist);
+  if (clist_row->style == style)
+    return;
 
-  /* Since we don't have a _remove method, unparent the children
-   * instead of destroying them so the focus will be unset properly.
-   * (For other containers, the _remove method takes care of the
-   * unparent) The destroy will happen when the refcount drops
-   * to zero.
-   */
+  old_width = g_new (gint, clist->columns);
 
-  /* destroy the scrollbars */
-  if (clist->vscrollbar)
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
     {
-      gtk_widget_unparent (clist->vscrollbar);
-      clist->vscrollbar = NULL;
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                          i, &requisition);
+           old_width[i] = requisition.width;
+         }
     }
-  if (clist->hscrollbar)
+
+  if (clist_row->style)
     {
-      gtk_widget_unparent (clist->hscrollbar);
-      clist->hscrollbar = NULL;
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->style);
+      gtk_style_unref (clist_row->style);
     }
 
-  if (clist->htimer)
+  clist_row->style = style;
+
+  if (clist_row->style)
     {
-      gtk_timeout_remove (clist->htimer);
-      clist->htimer = 0;
+      gtk_style_ref (clist_row->style);
+      
+      if (GTK_WIDGET_REALIZED (clist))
+        clist_row->style = gtk_style_attach (clist_row->style,
+                                            clist->clist_window);
     }
-  if (clist->vtimer)
+
+  if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
     {
-      gtk_timeout_remove (clist->vtimer);
-      clist->vtimer = 0;
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         column_auto_resize (clist, clist_row, i, old_width[i]);
     }
 
-  /* destroy the column buttons */
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].button)
-      {
-       gtk_widget_unparent (clist->column[i].button);
-       clist->column[i].button = NULL;
-      }
+  g_free (old_width);
 
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+  /* redraw the list if it's not frozen */
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+    }
 }
 
-static void
-gtk_clist_finalize (GtkObject * object)
+GtkStyle *
+gtk_clist_get_row_style (GtkCList *clist,
+                        gint      row)
 {
-  GtkCList *clist;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_CLIST (object));
+  GtkCListRow *clist_row;
 
-  clist = GTK_CLIST (object);
+  g_return_val_if_fail (clist != NULL, NULL);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
-  columns_delete (clist);
+  if (row < 0 || row >= clist->rows)
+    return NULL;
 
-  g_mem_chunk_destroy (clist->cell_mem_chunk);
-  g_mem_chunk_destroy (clist->row_mem_chunk);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  if (GTK_OBJECT_CLASS (parent_class)->finalize)
-    (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
+  return clist_row->style;
 }
 
-/*
- * GTKWIDGET
- *   gtk_clist_realize
- *   gtk_clist_unrealize
- *   gtk_clist_map
- *   gtk_clist_unmap
- *   gtk_clist_draw
- *   gtk_clist_expose
- *   gtk_clist_button_press
- *   gtk_clist_button_release
- *   gtk_clist_motion
- *   gtk_clist_size_request
- *   gtk_clist_size_allocate
+/* PUBLIC SELECTION FUNCTIONS
+ *   gtk_clist_set_selectable
+ *   gtk_clist_get_selectable
+ *   gtk_clist_select_row
+ *   gtk_clist_unselect_row
+ *   gtk_clist_select_all
+ *   gtk_clist_unselect_all
+ *   gtk_clist_undo_selection
  */
-static void
-gtk_clist_realize (GtkWidget * widget)
+void
+gtk_clist_set_selectable (GtkCList *clist,
+                         gint      row,
+                         gboolean  selectable)
 {
-  GtkCList *clist;
-  GdkWindowAttr attributes;
-  GdkGCValues values;
   GtkCListRow *clist_row;
-  GList *list;
-  gint attributes_mask;
-  gint border_width;
-  gint i;
-  gint j;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  clist = GTK_CLIST (widget);
+  if (row < 0 || row >= clist->rows)
+    return;
 
-  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  add_style_data (clist);
+  if (selectable == clist_row->selectable)
+    return;
 
-  border_width = GTK_CONTAINER (widget)->border_width;
-  
-  attributes.window_type = GDK_WINDOW_CHILD;
-  attributes.x = widget->allocation.x + border_width;
-  attributes.y = widget->allocation.y + border_width;
-  attributes.width = widget->allocation.width - border_width * 2;
-  attributes.height = widget->allocation.height - border_width * 2;
-  attributes.wclass = GDK_INPUT_OUTPUT;
-  attributes.visual = gtk_widget_get_visual (widget);
-  attributes.colormap = gtk_widget_get_colormap (widget);
-  attributes.event_mask = gtk_widget_get_events (widget);
-  attributes.event_mask |= (GDK_EXPOSURE_MASK |
-                           GDK_BUTTON_PRESS_MASK |
-                           GDK_BUTTON_RELEASE_MASK |
-                           GDK_KEY_PRESS_MASK |
-                           GDK_KEY_RELEASE_MASK);
-  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+  clist_row->selectable = selectable;
 
-  /* main window */
-  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
-                                  &attributes, attributes_mask);
-  gdk_window_set_user_data (widget->window, clist);
+  if (!selectable && clist_row->state == GTK_STATE_SELECTED)
+    {
+      if (clist->anchor >= 0 &&
+         clist->selection_mode == GTK_SELECTION_EXTENDED)
+       {
+         if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)))
+           {
+             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
+             gtk_grab_remove (GTK_WIDGET (clist));
+             gdk_pointer_ungrab (GDK_CURRENT_TIME);
+             if (clist->htimer)
+               {
+                 gtk_timeout_remove (clist->htimer);
+                 clist->htimer = 0;
+               }
+             if (clist->vtimer)
+               {
+                 gtk_timeout_remove (clist->vtimer);
+                 clist->vtimer = 0;
+               }
+           }
+         GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+       }
+      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+                      row, -1, NULL);
+    }      
+}
 
-  widget->style = gtk_style_attach (widget->style, widget->window);
+gboolean
+gtk_clist_get_selectable (GtkCList *clist,
+                         gint      row)
+{
+  g_return_val_if_fail (clist != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
 
-  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+  if (row < 0 || row >= clist->rows)
+    return FALSE;
 
-  /* column-title window */
+  return GTK_CLIST_ROW (g_list_nth (clist->row_list, row))->selectable;
+}
 
-  attributes.x = clist->column_title_area.x;
-  attributes.y = clist->column_title_area.y;
-  attributes.width = clist->column_title_area.width;
-  attributes.height = clist->column_title_area.height;
-  
-  clist->title_window = gdk_window_new (widget->window, &attributes,
-                                       attributes_mask);
-  gdk_window_set_user_data (clist->title_window, clist);
+void
+gtk_clist_select_row (GtkCList *clist,
+                     gint      row,
+                     gint      column)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  gtk_style_set_background (widget->style, clist->title_window,
-                           GTK_STATE_SELECTED);
-  gdk_window_show (clist->title_window);
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
 
-  /* set things up so column buttons are drawn in title window */
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].button)
-      gtk_widget_set_parent_window (clist->column[i].button,
-                                   clist->title_window);
+  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                  row, column, NULL);
+}
 
-  /* clist-window */
-  attributes.x = (clist->internal_allocation.x +
-                 widget->style->klass->xthickness);
-  attributes.y = (clist->internal_allocation.y +
-                 widget->style->klass->ythickness +
-                 clist->column_title_area.height);
-  attributes.width = clist->clist_window_width;
-  attributes.height = clist->clist_window_height;
-  
-  clist->clist_window = gdk_window_new (widget->window, &attributes,
-                                       attributes_mask);
-  gdk_window_set_user_data (clist->clist_window, clist);
+void
+gtk_clist_unselect_row (GtkCList *clist,
+                       gint      row,
+                       gint      column)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  gdk_window_set_background (clist->clist_window,
-                            &widget->style->bg[GTK_STATE_PRELIGHT]);
-  gdk_window_show (clist->clist_window);
-  gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
-                      &clist->clist_window_height);
+  if (row < 0 || row >= clist->rows)
+    return;
+  if (column < -1 || column >= clist->columns)
+    return;
 
-  /* create resize windows */
-  attributes.wclass = GDK_INPUT_ONLY;
-  attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
-                          GDK_BUTTON_RELEASE_MASK |
-                          GDK_POINTER_MOTION_MASK |
-                          GDK_POINTER_MOTION_HINT_MASK |
-                          GDK_KEY_PRESS_MASK);
-  attributes_mask = GDK_WA_CURSOR;
-  attributes.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
-  clist->cursor_drag = attributes.cursor;
+  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+                  row, column, NULL);
+}
 
-  attributes.x =  LIST_WIDTH (clist) + 1;
-  attributes.y = 0;
-  attributes.width = 0;
-  attributes.height = 0;
+void
+gtk_clist_select_all (GtkCList *clist)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  for (i = 0; i < clist->columns; i++)
-    {
-      clist->column[i].window = gdk_window_new (clist->title_window,
-                                               &attributes, attributes_mask);
-      gdk_window_set_user_data (clist->column[i].window, clist);
-    }
+  GTK_CLIST_CLASS_FW (clist)->select_all (clist);
+}
 
-  /* This is slightly less efficient than creating them with the
-   * right size to begin with, but easier
-   */
-  size_allocate_title_buttons (clist);
+void
+gtk_clist_unselect_all (GtkCList *clist)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  /* GCs */
-  clist->fg_gc = gdk_gc_new (widget->window);
-  clist->bg_gc = gdk_gc_new (widget->window);
-  
-  /* We'll use this gc to do scrolling as well */
-  gdk_gc_set_exposures (clist->fg_gc, TRUE);
+  GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
+}
 
-  values.foreground = widget->style->white;
-  values.function = GDK_XOR;
-  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
-  clist->xor_gc = gdk_gc_new_with_values (widget->window,
-                                         &values,
-                                         GDK_GC_FOREGROUND |
-                                         GDK_GC_FUNCTION |
-                                         GDK_GC_SUBWINDOW);
+void
+gtk_clist_undo_selection (GtkCList *clist)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  /* attach optional row/cell styles, allocate foreground/background colors */
-  list = clist->row_list;
-  for (i = 0; i < clist->rows; i++)
-    {
-      clist_row = list->data;
-      list = list->next;
+  if (clist->selection_mode == GTK_SELECTION_EXTENDED &&
+      (clist->undo_selection || clist->undo_unselection))
+    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
+}
 
-      if (clist_row->style)
-       clist_row->style = gtk_style_attach (clist_row->style,
-                                            clist->clist_window);
+/* PRIVATE SELECTION FUNCTIONS
+ *   selection_find
+ *   toggle_row
+ *   fake_toggle_row
+ *   toggle_focus_row
+ *   toggle_add_mode
+ *   real_select_row
+ *   real_unselect_row
+ *   real_select_all
+ *   real_unselect_all
+ *   fake_unselect_all
+ *   real_undo_selection
+ *   set_anchor
+ *   resync_selection
+ *   update_extended_selection
+ *   start_selection
+ *   end_selection
+ *   extend_selection
+ *   sync_selection
+ */
+static GList *
+selection_find (GtkCList *clist,
+               gint      row_number,
+               GList    *row_list_element)
+{
+  return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+}
 
-      if (clist_row->fg_set || clist_row->bg_set)
-       {
-         GdkColormap *colormap;
+static void
+toggle_row (GtkCList *clist,
+           gint      row,
+           gint      column,
+           GdkEvent *event)
+{
+  GtkCListRow *clist_row;
 
-         colormap = gtk_widget_get_colormap (widget);
-         if (clist_row->fg_set)
-           gdk_color_alloc (colormap, &clist_row->foreground);
-         if (clist_row->bg_set)
-           gdk_color_alloc (colormap, &clist_row->background);
+  switch (clist->selection_mode)
+    {
+    case GTK_SELECTION_EXTENDED:
+    case GTK_SELECTION_MULTIPLE:
+    case GTK_SELECTION_SINGLE:
+      clist_row = g_list_nth (clist->row_list, row)->data;
+      if (clist_row->state == GTK_STATE_SELECTED)
+       {
+         gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+                          row, column, event);
+         return;
        }
-      
-      for (j = 0; j < clist->columns; j++)
-       if  (clist_row->cell[j].style)
-         clist_row->cell[j].style =
-           gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
+    case GTK_SELECTION_BROWSE:
+      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                      row, column, event);
+      break;
     }
 }
 
 static void
-gtk_clist_unrealize (GtkWidget * widget)
+fake_toggle_row (GtkCList *clist,
+                gint      row)
 {
-  gint i;
-  GtkCList *clist;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
+  GList *work;
 
-  clist = GTK_CLIST (widget);
+  if (!(work = g_list_nth (clist->row_list, row))||
+      !GTK_CLIST_ROW (work)->selectable)
+    return;
+  
+  if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
+    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
+  else
+    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+  
+  if (!GTK_CLIST_FROZEN (clist) &&
+      gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
+                                         GTK_CLIST_ROW (work));
+}
 
-  GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+static void
+toggle_focus_row (GtkCList *clist)
+{
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  /* detach optional row/cell styles */
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+      clist->focus_row < 0 || clist->focus_row >= clist->rows)
+    return;
 
-  if (GTK_WIDGET_REALIZED (widget))
+  switch (clist->selection_mode)
     {
-      GtkCListRow *clist_row;
-      GList *list;
-      gint j;
+    case  GTK_SELECTION_SINGLE:
+    case  GTK_SELECTION_MULTIPLE:
+      toggle_row (clist, clist->focus_row, 0, NULL);
+      break;
+    case GTK_SELECTION_EXTENDED:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
 
-      list = clist->row_list;
-      for (i = 0; i < clist->rows; i++)
-       {
-         clist_row = list->data;
-         list = list->next;
+      clist->anchor = clist->focus_row;
+      clist->drag_pos = clist->focus_row;
+      clist->undo_anchor = clist->focus_row;
+      
+      if (GTK_CLIST_ADD_MODE (clist))
+       fake_toggle_row (clist, clist->focus_row);
+      else
+       GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
 
-         if (clist_row->style)
-           gtk_style_detach (clist_row->style);
-         for (j = 0; j < clist->columns; j++)
-           if  (clist_row->cell[j].style)
-             gtk_style_detach (clist_row->cell[j].style);
-       }
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+      break;
+    default:
+      break;
     }
-
-  gdk_cursor_destroy (clist->cursor_drag);
-  gdk_gc_destroy (clist->xor_gc);
-  gdk_gc_destroy (clist->fg_gc);
-  gdk_gc_destroy (clist->bg_gc);
-
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].window)
-      {
-       gdk_window_set_user_data (clist->column[i].window, NULL);
-       gdk_window_destroy (clist->column[i].window);
-       clist->column[i].window = NULL;
-      }
-
-  gdk_window_set_user_data (clist->clist_window, NULL);
-  gdk_window_destroy (clist->clist_window);
-  clist->clist_window = NULL;
-
-  gdk_window_set_user_data (clist->title_window, NULL);
-  gdk_window_destroy (clist->title_window);
-  clist->title_window = NULL;
-
-  clist->cursor_drag = NULL;
-  clist->xor_gc = NULL;
-  clist->fg_gc = NULL;
-  clist->bg_gc = NULL;
-
-  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
-    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 }
 
 static void
-gtk_clist_map (GtkWidget * widget)
+toggle_add_mode (GtkCList *clist)
 {
-  gint i;
-  GtkCList *clist;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  clist = GTK_CLIST (widget);
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+      clist->selection_mode != GTK_SELECTION_EXTENDED)
+    return;
 
-  if (!GTK_WIDGET_MAPPED (widget))
+  gtk_clist_draw_focus (GTK_WIDGET (clist));
+  if (!GTK_CLIST_ADD_MODE (clist))
     {
-      GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
-
-      gdk_window_show (widget->window);
-      gdk_window_show (clist->title_window);
-      gdk_window_show (clist->clist_window);
-
-      /* map column buttons */
-      for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].button &&
-           GTK_WIDGET_VISIBLE (clist->column[i].button) &&
-           !GTK_WIDGET_MAPPED (clist->column[i].button))
-         gtk_widget_map (clist->column[i].button);
-      
-      /* map resize windows AFTER column buttons (above) */
-      for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].window && clist->column[i].button)
-         gdk_window_show (clist->column[i].window);
-       
-      /* map vscrollbars */
-      if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
-         !GTK_WIDGET_MAPPED (clist->vscrollbar))
-       gtk_widget_map (clist->vscrollbar);
-
-      if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
-         !GTK_WIDGET_MAPPED (clist->hscrollbar))
-       gtk_widget_map (clist->hscrollbar);
-
-      /* unfreeze the list */
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
+      GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
+      gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                 GDK_LINE_ON_OFF_DASH, 0, 0);
+      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
     }
+  else
+    {
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+      clist->anchor_state = GTK_STATE_SELECTED;
+    }
+  gtk_clist_draw_focus (GTK_WIDGET (clist));
 }
 
 static void
-gtk_clist_unmap (GtkWidget * widget)
+real_select_row (GtkCList *clist,
+                gint      row,
+                gint      column,
+                GdkEvent *event)
 {
-  gint i;
-  GtkCList *clist;
+  GtkCListRow *clist_row;
+  GList *list;
+  gint sel_row;
+  gboolean row_selected;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  clist = GTK_CLIST (widget);
+  if (row < 0 || row > (clist->rows - 1))
+    return;
 
-  if (GTK_WIDGET_MAPPED (widget))
+  switch (clist->selection_mode)
     {
-      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
 
-      for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].window)
-         gdk_window_hide (clist->column[i].window);
+      row_selected = FALSE;
+      list = clist->selection;
 
-      gdk_window_hide (clist->clist_window);
-      gdk_window_hide (clist->title_window);
-      gdk_window_hide (widget->window);
+      while (list)
+       {
+         sel_row = GPOINTER_TO_INT (list->data);
+         list = list->next;
 
-      /* unmap scrollbars */
-      if (GTK_WIDGET_MAPPED (clist->vscrollbar))
-       gtk_widget_unmap (clist->vscrollbar);
+         if (row == sel_row)
+           row_selected = TRUE;
+         else
+           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
+                            sel_row, column, event);
+       }
 
-      if (GTK_WIDGET_MAPPED (clist->hscrollbar))
-       gtk_widget_unmap (clist->hscrollbar);
+      if (row_selected)
+       return;
+      
+    default:
+      break;
+    }
 
-      /* unmap column buttons */
-      for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].button &&
-           GTK_WIDGET_MAPPED (clist->column[i].button))
-         gtk_widget_unmap (clist->column[i].button);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-      /* freeze the list */
-      GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+  if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
+    return;
+
+  clist_row->state = GTK_STATE_SELECTED;
+  if (!clist->selection)
+    {
+      clist->selection = g_list_append (clist->selection,
+                                       GINT_TO_POINTER (row));
+      clist->selection_end = clist->selection;
     }
+  else
+    clist->selection_end = 
+      g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
+  
+  if (!GTK_CLIST_FROZEN (clist)
+      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
 }
 
 static void
-gtk_clist_draw (GtkWidget * widget,
-               GdkRectangle * area)
+real_unselect_row (GtkCList *clist,
+                  gint      row,
+                  gint      column,
+                  GdkEvent *event)
 {
-  GtkCList *clist;
-  gint border_width;
-  GdkRectangle child_area;
-  int i;
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
-  g_return_if_fail (area != NULL);
+  GtkCListRow *clist_row;
 
-  if (GTK_WIDGET_DRAWABLE (widget))
-    {
-      clist = GTK_CLIST (widget);
-      border_width = GTK_CONTAINER (widget)->border_width;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-      gdk_window_clear_area (widget->window,
-                            area->x - border_width, 
-                            area->y - border_width,
-                            area->width, area->height);
+  if (row < 0 || row > (clist->rows - 1))
+    return;
 
-      /* draw list shadow/border */
-      gtk_draw_shadow (widget->style, widget->window,
-                      GTK_STATE_NORMAL, clist->shadow_type,
-                      0, 0, 
-                      clist->clist_window_width + (2 * widget->style->klass->xthickness),
-                      clist->clist_window_height + (2 * widget->style->klass->ythickness) +
-                      clist->column_title_area.height);
+  clist_row = (g_list_nth (clist->row_list, row))->data;
 
-      gdk_window_clear_area (clist->clist_window,
-                            0, 0, -1, -1);
+  if (clist_row->state == GTK_STATE_SELECTED)
+    {
+      clist_row->state = GTK_STATE_NORMAL;
 
-      draw_rows (clist, NULL);
+      if (clist->selection_end && 
+         clist->selection_end->data == GINT_TO_POINTER (row))
+       clist->selection_end = clist->selection_end->prev;
 
-      for (i = 0; i < clist->columns; i++)
-       {
-         if (!clist->column[i].visible)
-           continue;
-         if (gtk_widget_intersect (clist->column[i].button, area, &child_area))
-           gtk_widget_draw (clist->column[i].button, &child_area);
-       }
+      clist->selection = g_list_remove (clist->selection,
+                                       GINT_TO_POINTER (row));
+      
+      if (!GTK_CLIST_FROZEN (clist)
+         && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
     }
 }
 
-static gint
-gtk_clist_expose (GtkWidget * widget,
-                 GdkEventExpose * event)
+static void
+real_select_all (GtkCList *clist)
 {
-  GtkCList *clist;
+  GList *list;
+  gint i;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    return;
 
-  if (GTK_WIDGET_DRAWABLE (widget))
+  switch (clist->selection_mode)
     {
-      clist = GTK_CLIST (widget);
+    case GTK_SELECTION_SINGLE:
+    case GTK_SELECTION_BROWSE:
+      return;
 
-      /* draw border */
-      if (event->window == widget->window)
-       gtk_draw_shadow (widget->style, widget->window,
-                        GTK_STATE_NORMAL, clist->shadow_type,
-                        0, 0,
-                        clist->clist_window_width + (2 * widget->style->klass->xthickness),
-                        clist->clist_window_height + (2 * widget->style->klass->ythickness) +
-                        clist->column_title_area.height);
+    case GTK_SELECTION_EXTENDED:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+         
+      if (clist->rows &&
+         ((GtkCListRow *) (clist->row_list->data))->state !=
+         GTK_STATE_SELECTED)
+       fake_toggle_row (clist, 0);
 
-      /* exposure events on the list */
-      if (event->window == clist->clist_window)
-       draw_rows (clist, &event->area);
-    }
+      clist->anchor_state =  GTK_STATE_SELECTED;
+      clist->anchor = 0;
+      clist->drag_pos = 0;
+      clist->undo_anchor = clist->focus_row;
+      update_extended_selection (clist, clist->rows);
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+      return;
 
-  return FALSE;
+    case GTK_SELECTION_MULTIPLE:
+      for (i = 0, list = clist->row_list; list; i++, list = list->next)
+       {
+         if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
+           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                            i, -1, NULL);
+       }
+      return;
+    }
 }
 
-static gint
-gtk_clist_button_press (GtkWidget * widget,
-                       GdkEventButton * event)
+static void
+real_unselect_all (GtkCList *clist)
 {
+  GList *list;
   gint i;
-  GtkCList *clist;
-  gint x;
-  gint y;
-  gint row;
-  gint column;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  clist = GTK_CLIST (widget);
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    return;
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
-    return FALSE;
-  
-  /* selections on the list */
-  if (event->window == clist->clist_window)
+  switch (clist->selection_mode)
     {
-      x = event->x;
-      y = event->y;
-
-      if (get_selection_info (clist, x, y, &row, &column))
+    case GTK_SELECTION_BROWSE:
+      if (clist->focus_row >= 0)
        {
-         gint old_row = clist->focus_row;
+         gtk_signal_emit (GTK_OBJECT (clist),
+                          clist_signals[SELECT_ROW],
+                          clist->focus_row, -1, NULL);
+         return;
+       }
+      break;
+    case GTK_SELECTION_EXTENDED:
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
 
-         if (clist->focus_row == -1)
-           old_row = row;
+      clist->anchor = -1;
+      clist->drag_pos = -1;
+      clist->undo_anchor = clist->focus_row;
+      break;
+    default:
+      break;
+    }
 
-         if (event->type == GDK_BUTTON_PRESS)
-           {
-             GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gdk_pointer_grab (clist->clist_window, FALSE,
-                               GDK_POINTER_MOTION_HINT_MASK |
-                               GDK_BUTTON1_MOTION_MASK |
-                               GDK_BUTTON_RELEASE_MASK,
-                               NULL, NULL, event->time);
-             gtk_grab_add (widget);
-           }
-         else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
-           {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-             gtk_grab_remove (widget);
-             gdk_pointer_ungrab (event->time);
-           }
+  list = clist->selection;
+  while (list)
+    {
+      i = GPOINTER_TO_INT (list->data);
+      list = list->next;
+      gtk_signal_emit (GTK_OBJECT (clist),
+                      clist_signals[UNSELECT_ROW], i, -1, NULL);
+    }
+}
 
-         if (GTK_CLIST_ADD_MODE (clist))
-           {
-             GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
-             if (GTK_WIDGET_HAS_FOCUS (widget))
-               {
-                 gtk_clist_draw_focus (widget);
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
-               }
-             else
-               {
-                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                             GDK_LINE_SOLID, 0, 0);
-                 clist->focus_row = row;
-               }
-           }
-         else if (row != clist->focus_row)
-           {
-             if (GTK_WIDGET_HAS_FOCUS (widget))
-               {
-                 gtk_clist_draw_focus (widget);
-                 clist->focus_row = row;
-                 gtk_clist_draw_focus (widget);
-               }
-             else
-               clist->focus_row = row;
-           }
+static void
+fake_unselect_all (GtkCList *clist,
+                  gint      row)
+{
+  GList *list;
+  GList *work;
+  gint i;
 
-         if (!GTK_WIDGET_HAS_FOCUS (widget))
-           gtk_widget_grab_focus (widget);
+  if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
+    {
+      if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
+         GTK_CLIST_ROW (work)->selectable)
+       {
+         GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
+         
+         if (!GTK_CLIST_FROZEN (clist) &&
+             gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
+           GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
+                                                 GTK_CLIST_ROW (work));
+       }  
+    }
 
-         switch (clist->selection_mode)
-           {
-           case GTK_SELECTION_SINGLE:
-           case GTK_SELECTION_MULTIPLE:
-             if (event->type != GDK_BUTTON_PRESS)
-               select_row (clist, row, column, (GdkEvent *) event);
-             else
-               clist->anchor = row;
-             break;
+  clist->undo_selection = clist->selection;
+  clist->selection = NULL;
+  clist->selection_end = NULL;
+  
+  for (list = clist->undo_selection; list; list = list->next)
+    {
+      if ((i = GPOINTER_TO_INT (list->data)) == row ||
+         !(work = g_list_nth (clist->row_list, i)))
+       continue;
 
-           case GTK_SELECTION_BROWSE:
-             select_row (clist, row, column, (GdkEvent *) event);
-             break;
+      GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+      if (!GTK_CLIST_FROZEN (clist) &&
+         gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
+       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
+                                             GTK_CLIST_ROW (work));
+    }
+}
 
-           case GTK_SELECTION_EXTENDED:
-             if (event->type != GDK_BUTTON_PRESS)
-               {
-                 if (clist->anchor != -1)
-                   {
-                     update_extended_selection (clist, clist->focus_row);
-                     GTK_CLIST_CLASS_FW (clist)->resync_selection
-                       (clist, (GdkEvent *) event);
-                   }
-                 select_row (clist, row, column, (GdkEvent *) event);
-                 break;
-               }
-             
-             if (event->state & GDK_CONTROL_MASK)
-               {
-                 if (event->state & GDK_SHIFT_MASK)
-                   {
-                     if (clist->anchor < 0)
-                       {
-                         g_list_free (clist->undo_selection);
-                         g_list_free (clist->undo_unselection);
-                         clist->undo_selection = NULL;
-                         clist->undo_unselection = NULL;
-                         clist->anchor = old_row;
-                         clist->drag_pos = old_row;
-                         clist->undo_anchor = old_row;
-                       }
-                     update_extended_selection (clist, clist->focus_row);
-                   }
-                 else
-                   {
-                     if (clist->anchor == -1)
-                       set_anchor (clist, TRUE, row, old_row);
-                     else
-                       update_extended_selection (clist, clist->focus_row);
-                   }
-                 break;
-               }
+static void
+real_undo_selection (GtkCList *clist)
+{
+  GList *work;
 
-             if (event->state & GDK_SHIFT_MASK)
-               {
-                 set_anchor (clist, FALSE, old_row, old_row);
-                 update_extended_selection (clist, clist->focus_row);
-                 break;
-               }
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-             if (clist->anchor == -1)
-               set_anchor (clist, FALSE, row, old_row);
-             else
-               update_extended_selection (clist, clist->focus_row);
-             break;
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+      clist->selection_mode != GTK_SELECTION_EXTENDED)
+    return;
 
-           default:
-             break;
-           }
-       }
+  if (clist->anchor >= 0)
+    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 
-      return FALSE;
+  if (!(clist->undo_selection || clist->undo_unselection))
+    {
+      gtk_clist_unselect_all (clist);
+      return;
     }
 
-  /* press on resize windows */
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].resizeable && clist->column[i].window &&
-       event->window == clist->column[i].window)
-      {
-       gdk_pointer_grab (clist->column[i].window, FALSE,
-                         GDK_POINTER_MOTION_HINT_MASK |
-                         GDK_BUTTON1_MOTION_MASK |
-                         GDK_BUTTON_RELEASE_MASK,
-                         NULL, NULL, event->time);
-       gtk_grab_add (widget);
-       GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
-
-       if (!GTK_WIDGET_HAS_FOCUS (widget))
-         gtk_widget_grab_focus (widget);
+  for (work = clist->undo_selection; work; work = work->next)
+    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                    GPOINTER_TO_INT (work->data), -1, NULL);
 
-       clist->drag_pos = i;
-       clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
-                        clist->column[i].area.width + CELL_SPACING);
+  for (work = clist->undo_unselection; work; work = work->next)
+    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
+                    GPOINTER_TO_INT (work->data), -1, NULL);
 
-       if (GTK_CLIST_ADD_MODE (clist))
-         gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
-       draw_xor_line (clist);
+  if (GTK_WIDGET_HAS_FOCUS (clist) && clist->focus_row != clist->undo_anchor)
+    {
+      gtk_clist_draw_focus (GTK_WIDGET (clist));
+      clist->focus_row = clist->undo_anchor;
+      gtk_clist_draw_focus (GTK_WIDGET (clist));
+    }
+  else
+    clist->focus_row = clist->undo_anchor;
+  
+  clist->undo_anchor = -1;
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
 
-       return FALSE;
-      }
-  return FALSE;
+  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+      clist->clist_window_height)
+    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 }
 
-static gint
-gtk_clist_button_release (GtkWidget * widget,
-                         GdkEventButton * event)
+static void
+set_anchor (GtkCList *clist,
+           gboolean  add_mode,
+           gint      anchor,
+           gint      undo_anchor)
 {
-  GtkCList *clist;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  clist = GTK_CLIST (widget);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+  
+  if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
+    return;
 
-  /* we don't handle button 2 and 3 */
-  if (event->button != 1)
-    return FALSE;
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
 
-  /* release on resize windows */
-  if (GTK_CLIST_IN_DRAG (clist))
+  if (add_mode)
+    fake_toggle_row (clist, anchor);
+  else
     {
-      gint width;
-      gint x;
-      gint i;
-
-      i = clist->drag_pos;
-      clist->drag_pos = -1;
+      GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
+      clist->anchor_state = GTK_STATE_SELECTED;
+    }
 
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
-      gtk_widget_get_pointer (widget, &x, NULL);
-      gtk_grab_remove (widget);
-      gdk_pointer_ungrab (event->time);
+  clist->anchor = anchor;
+  clist->drag_pos = anchor;
+  clist->undo_anchor = undo_anchor;
+}
 
-      if (clist->x_drag >= 0)
-       draw_xor_line (clist);
+static void
+resync_selection (GtkCList *clist,
+                 GdkEvent *event)
+{
+  gint i;
+  gint e;
+  gint row;
+  gboolean thaw = FALSE;
+  GList *list;
+  GtkCListRow *clist_row;
 
-      if (GTK_CLIST_ADD_MODE (clist))
-       {
-         gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                     GDK_LINE_ON_OFF_DASH, 0, 0);
-         gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
-       }
+  if (clist->anchor < 0)
+    return;
 
-      width = new_column_width (clist, i, &x);
-      resize_column (clist, i, width);
-      return FALSE;
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+      thaw = TRUE;
     }
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
-    {
-      gint row;
-      gint column;
+  i = MIN (clist->anchor, clist->drag_pos);
+  e = MAX (clist->anchor, clist->drag_pos);
 
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
-      gtk_grab_remove (widget);
-      gdk_pointer_ungrab (event->time);
-      if (clist->htimer)
-       {
-         gtk_timeout_remove (clist->htimer);
-         clist->htimer = 0;
-       }
-      if (clist->vtimer)
-       {
-         gtk_timeout_remove (clist->vtimer);
-         clist->vtimer = 0;
-       }
-      switch (clist->selection_mode)
+  if (clist->undo_selection)
+    {
+      list = clist->selection;
+      clist->selection = clist->undo_selection;
+      clist->selection_end = g_list_last (clist->selection);
+      clist->undo_selection = list;
+      list = clist->selection;
+      while (list)
        {
-       case GTK_SELECTION_EXTENDED:
-         if (!(event->state & GDK_SHIFT_MASK) ||
-             event->x < 0 || event->x >= clist->clist_window_width ||
-             event->y < 0 || event->y >= clist->clist_window_height)
-           GTK_CLIST_CLASS_FW (clist)->resync_selection
-             (clist, (GdkEvent *) event);
-         break;
-
-       case GTK_SELECTION_SINGLE:
-       case GTK_SELECTION_MULTIPLE:
-         if (get_selection_info (clist, event->x, event->y, &row, &column))
+         row = GPOINTER_TO_INT (list->data);
+         list = list->next;
+         if (row < i || row > e)
            {
-             if (clist->anchor == clist->focus_row)
-               toggle_row (clist, row, column, (GdkEvent *) event);
+             clist_row = g_list_nth (clist->row_list, row)->data;
+             if (clist_row->selectable)
+               {
+                 clist_row->state = GTK_STATE_SELECTED;
+                 gtk_signal_emit (GTK_OBJECT (clist),
+                                  clist_signals[UNSELECT_ROW],
+                                  row, -1, event);
+                 clist->undo_selection = g_list_prepend
+                   (clist->undo_selection, GINT_TO_POINTER (row));
+               }
            }
-         clist->anchor = -1;
-         break;
-
-       default:
-         break;
        }
-    }
-
-  return FALSE;
-}
-
-static gint
-horizontal_timeout (GtkCList *clist)
-{
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
-
-  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+    }    
 
-  clist->htimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+  for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
+    if (GTK_CLIST_ROW (list)->selectable)
+      {
+       if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
+         {
+           if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
+             {
+               GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+               gtk_signal_emit (GTK_OBJECT (clist),
+                                clist_signals[UNSELECT_ROW], i, -1, event);
+               clist->undo_selection = g_list_prepend (clist->undo_selection,
+                                                       GINT_TO_POINTER (i));
+             }
+         }
+       else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+         {
+           GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+           clist->undo_unselection = g_list_prepend (clist->undo_unselection,
+                                                     GINT_TO_POINTER (i));
+         }
+      }
 
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
+  for (list = clist->undo_unselection; list; list = list->next)
+    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                    GPOINTER_TO_INT (list->data), -1, event);
 
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
+  clist->anchor = -1;
+  clist->drag_pos = -1;
 
-  return FALSE;
+  if (thaw)
+    GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
 }
 
-static gint
-vertical_timeout (GtkCList *clist)
+static void
+update_extended_selection (GtkCList *clist,
+                          gint      row)
 {
-  gint x, y;
-  GdkEventMotion event;
-  GdkModifierType mask;
+  gint i;
+  GList *list;
+  GdkRectangle area;
+  gint s1 = -1;
+  gint s2 = -1;
+  gint e1 = -1;
+  gint e2 = -1;
+  gint y1 = clist->clist_window_height;
+  gint y2 = clist->clist_window_height;
+  gint h1 = 0;
+  gint h2 = 0;
+  gint top;
 
-  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+  if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
+    return;
 
-  clist->vtimer = 0;
-  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+  if (row < 0)
+    row = 0;
+  if (row >= clist->rows)
+    row = clist->rows - 1;
 
-  event.is_hint = 0;
-  event.x = x;
-  event.y = y;
-  event.state = mask;
+  /* extending downwards */
+  if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
+    {
+      s2 = clist->drag_pos + 1;
+      e2 = row;
+    }
+  /* extending upwards */
+  else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
+    {
+      s2 = row;
+      e2 = clist->drag_pos - 1;
+    }
+  else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
+    {
+      e1 = clist->drag_pos;
+      /* row and drag_pos on different sides of anchor :
+        take back the selection between anchor and drag_pos,
+         select between anchor and row */
+      if (row < clist->anchor)
+       {
+         s1 = clist->anchor + 1;
+         s2 = row;
+         e2 = clist->anchor - 1;
+       }
+      /* take back the selection between anchor and drag_pos */
+      else
+       s1 = row + 1;
+    }
+  else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
+    {
+      s1 = clist->drag_pos;
+      /* row and drag_pos on different sides of anchor :
+        take back the selection between anchor and drag_pos,
+         select between anchor and row */
+      if (row > clist->anchor)
+       {
+         e1 = clist->anchor - 1;
+         s2 = clist->anchor + 1;
+         e2 = row;
+       }
+      /* take back the selection between anchor and drag_pos */
+      else
+       e1 = row - 1;
+    }
 
-  gtk_clist_motion (GTK_WIDGET (clist), &event);
+  clist->drag_pos = row;
 
-  return FALSE;
+  area.x = 0;
+  area.width = clist->clist_window_width;
+
+  /* restore the elements between s1 and e1 */
+  if (s1 >= 0)
+    {
+      for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
+          i++, list = list->next)
+       if (GTK_CLIST_ROW (list)->selectable)
+         {
+           if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
+             GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
+           else
+             GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
+         }
+
+      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+      if (top + clist->row_height <= 0)
+       {
+         area.y = 0;
+         area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
+         draw_rows (clist, &area);
+         gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+       }
+      else if (top >= clist->clist_window_height)
+       {
+         area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
+         area.height = clist->clist_window_height - area.y;
+         draw_rows (clist, &area);
+         gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+       }
+      else if (top < 0)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+      else if (top + clist->row_height > clist->clist_window_height)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+      y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
+      h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
+    }
+
+  /* extend the selection between s2 and e2 */
+  if (s2 >= 0)
+    {
+      for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
+          i++, list = list->next)
+       if (GTK_CLIST_ROW (list)->selectable &&
+           GTK_CLIST_ROW (list)->state != clist->anchor_state)
+         GTK_CLIST_ROW (list)->state = clist->anchor_state;
+
+      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+
+      if (top + clist->row_height <= 0)
+       {
+         area.y = 0;
+         area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
+         draw_rows (clist, &area);
+         gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+       }
+      else if (top >= clist->clist_window_height)
+       {
+         area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
+         area.height = clist->clist_window_height - area.y;
+         draw_rows (clist, &area);
+         gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+       }
+      else if (top < 0)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+      else if (top + clist->row_height > clist->clist_window_height)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+
+      y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
+      h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
+    }
+
+  area.y = MAX (0, MIN (y1, y2));
+  if (area.y > clist->clist_window_height)
+    area.y = 0;
+  area.height = MIN (clist->clist_window_height, h1 + h2);
+  if (s1 >= 0 && s2 >= 0)
+    area.height += (clist->row_height + CELL_SPACING);
+  draw_rows (clist, &area);
 }
 
 static void
-move_vertical (GtkCList *clist,
-              gint row,
-              gfloat align)
+start_selection (GtkCList *clist)
 {
-  gint y;
-  GtkAdjustment *adj;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  adj = GTK_RANGE (clist->vscrollbar)->adjustment;
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    return;
 
-  y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
-  
-  y = y - align * (clist->clist_window_height - clist->row_height)
-    + (2 * align - 1) * CELL_SPACING;
-  
-  if (y + adj->page_size > adj->upper)
-    adj->value = adj->upper - adj->page_size;
-  else
-    adj->value = y;
+  set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+             clist->focus_row);
+}
 
-  gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
+static void
+end_selection (GtkCList *clist)
+{
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) ||
+      clist->anchor == -1)
+    return;
+  
+  GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 }
 
 static void
-move_horizontal (GtkCList *clist,
-                gint diff)
+extend_selection (GtkCList      *clist,
+                 GtkScrollType  scroll_type,
+                 gfloat         position,
+                 gboolean       auto_start_selection)
 {
-  gfloat upper;
-  GtkAdjustment *adj;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  adj = GTK_RANGE (clist->hscrollbar)->adjustment;
+  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
+      clist->selection_mode != GTK_SELECTION_EXTENDED)
+    return;
 
-  adj->value += diff;
+  if (auto_start_selection)
+    set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
+               clist->focus_row);
+  else if (clist->anchor == -1)
+    return;
 
-  upper = adj->upper - adj->page_size;
-  adj->value = MIN (adj->value, upper);
-  adj->value = MAX (adj->value, 0.0);
+  move_focus_row (clist, scroll_type, position);
 
-  gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
+  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+      clist->clist_window_height)
+    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+
+  update_extended_selection (clist, clist->focus_row);
 }
 
-static gint
-gtk_clist_motion (GtkWidget * widget,
-                 GdkEventMotion * event)
+static void
+sync_selection (GtkCList *clist,
+               gint      row,
+               gint      mode)
 {
-  GtkCList *clist;
-  gint x;
-  gint y;
-  gint row;
-  gint new_width;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-
-  clist = GTK_CLIST (widget);
-  if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
-    return FALSE;
+  GList *list;
+  gint d;
 
-  if (GTK_CLIST_IN_DRAG (clist))
-    {
-      if (event->is_hint || event->window != widget->window)
-       gtk_widget_get_pointer (widget, &x, NULL);
-      else
-       x = event->x;
+  if (mode == SYNC_INSERT)
+    d = 1;
+  else
+    d = -1;
       
-      new_width = new_column_width (clist, clist->drag_pos, &x);
-      if (x != clist->x_drag)
-       {
-         /* x_drag < 0 indicates that the xor line is already invisible */
-         if (clist->x_drag >= 0)
-           draw_xor_line (clist);
+  if (clist->focus_row >= row)
+    {
+      clist->focus_row += d;
+      if (clist->focus_row == -1 && clist->rows >= 1)
+       clist->focus_row = 0;
+    }
 
-         clist->x_drag = x;
+  if (clist->selection_mode == GTK_SELECTION_BROWSE && clist->anchor != -1)
+    GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
 
-         if (clist->x_drag >= 0)
-           draw_xor_line (clist);
-       }
+  g_list_free (clist->undo_selection);
+  g_list_free (clist->undo_unselection);
+  clist->undo_selection = NULL;
+  clist->undo_unselection = NULL;
 
-      if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
-                           clist->column[clist->drag_pos].min_width + 1))
-       {
-         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
-           gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
-         return FALSE;
-       }
-      if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
-         new_width >= clist->column[clist->drag_pos].max_width)
-       {
-         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
-             clist->clist_window_width && x < 0)
-           move_horizontal (clist,
-                            COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
-                            new_width - clist->clist_window_width +
-                            COLUMN_INSET + CELL_SPACING);
-         return FALSE;
-       }
-    }
-
-  if (event->is_hint || event->window != clist->clist_window)
-    gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
+  clist->anchor = -1;
+  clist->drag_pos = -1;
+  clist->undo_anchor = clist->focus_row;
 
-  /* horizontal autoscrolling */
-  if (LIST_WIDTH (clist) > clist->clist_window_width &&
-      (x < 0 || x >= clist->clist_window_width))
+  list = clist->selection;
+  while (list)
     {
-      if (clist->htimer)
-       return FALSE;
-
-      clist->htimer = gtk_timeout_add
-       (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
-
-      if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value == 0) ||
-           (x >= clist->clist_window_width &&
-            GTK_RANGE (clist->hscrollbar)->adjustment->value ==
-            LIST_WIDTH (clist) - clist->clist_window_width)))
-       {
-         if (x < 0)
-           move_horizontal (clist, -1 + (x/2));
-         else
-           move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
-       }
+      if (GPOINTER_TO_INT (list->data) >= row)
+       list->data = ((gchar*) list->data) + d;
+      list = list->next;
     }
+}
 
-  if (GTK_CLIST_IN_DRAG (clist))
-    return FALSE;
-
-  /* vertical autoscrolling */
-  row = ROW_FROM_YPIXEL (clist, y);
+/* GTKOBJECT
+ *   gtk_clist_destroy
+ *   gtk_clist_finalize
+ */
+static void
+gtk_clist_destroy (GtkObject *object)
+{
+  gint i;
+  GtkCList *clist;
 
-  /* don't scroll on last pixel row if it's a cell spacing */
-  if (y == clist->clist_window_height-1 &&
-      y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
-    return FALSE;
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_CLIST (object));
 
-  if (LIST_HEIGHT (clist) > clist->clist_window_height &&
-      (y < 0 || y >= clist->clist_window_height))
-    {
-      if (clist->vtimer)
-       return FALSE;
+  clist = GTK_CLIST (object);
 
-      clist->vtimer = gtk_timeout_add (SCROLL_TIME,
-                                      (GtkFunction) vertical_timeout, clist);
+  /* freeze the list */
+  GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
 
-      if (GTK_CLIST_DRAG_SELECTION (clist))
-       {
-         if ((y < 0 && clist->focus_row == 0) ||
-             (y >= clist->clist_window_height &&
-              clist->focus_row == clist->rows-1))
-           return FALSE;
-       }
-    }
+  /* get rid of all the rows */
+  gtk_clist_clear (clist);
 
-  row = CLAMP (row, 0, clist->rows - 1);
+  /* Since we don't have a _remove method, unparent the children
+   * instead of destroying them so the focus will be unset properly.
+   * (For other containers, the _remove method takes care of the
+   * unparent) The destroy will happen when the refcount drops
+   * to zero.
+   */
 
-  if (GTK_CLIST_DRAG_SELECTION (clist))
+  /* destroy the scrollbars */
+  if (clist->vscrollbar)
     {
-      if (row == clist->focus_row)
-       return FALSE;
-
-      gtk_clist_draw_focus (widget);
-      clist->focus_row = row;
-      gtk_clist_draw_focus (widget);
+      gtk_widget_unparent (clist->vscrollbar);
+      clist->vscrollbar = NULL;
+    }
+  if (clist->hscrollbar)
+    {
+      gtk_widget_unparent (clist->hscrollbar);
+      clist->hscrollbar = NULL;
+    }
 
-      switch (clist->selection_mode)
-       {
-       case GTK_SELECTION_BROWSE:
-         select_row (clist, clist->focus_row, - 1, (GdkEvent *) event);
-         break;
-         
-       case GTK_SELECTION_EXTENDED:
-         update_extended_selection (clist, clist->focus_row);
-         break;
-         
-       default:
-         break;
-       }
+  if (clist->htimer)
+    {
+      gtk_timeout_remove (clist->htimer);
+      clist->htimer = 0;
+    }
+  if (clist->vtimer)
+    {
+      gtk_timeout_remove (clist->vtimer);
+      clist->vtimer = 0;
     }
-  
-  if (ROW_TOP_YPIXEL(clist, row) < 0)
-    move_vertical (clist, row, 0);
-  else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
-          clist->clist_window_height)
-    move_vertical (clist, row, 1);
 
-  return FALSE;
+  /* destroy the column buttons */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      {
+       gtk_widget_unparent (clist->column[i].button);
+       clist->column[i].button = NULL;
+      }
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 }
 
 static void
-gtk_clist_size_request (GtkWidget * widget,
-                       GtkRequisition * requisition)
+gtk_clist_finalize (GtkObject *object)
 {
-  gint i;
   GtkCList *clist;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
-  g_return_if_fail (requisition != NULL);
-
-  clist = GTK_CLIST (widget);
-
-  add_style_data (clist);
-
-  requisition->width = 0;
-  requisition->height = 0;
-
-  /* compute the size of the column title (title) area */
-  clist->column_title_area.height = 0;
-  if (GTK_CLIST_SHOW_TITLES (clist))
-    for (i = 0; i < clist->columns; i++)
-      if (clist->column[i].button)
-       {
-         gtk_widget_size_request (clist->column[i].button,
-                                  &clist->column[i].button->requisition);
-         clist->column_title_area.height =
-           MAX (clist->column_title_area.height,
-                clist->column[i].button->requisition.height);
-       }
-  requisition->height += clist->column_title_area.height;
-
-  /* add the vscrollbar space */
-  if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
-      GTK_WIDGET_VISIBLE (clist->vscrollbar))
-    {
-      gtk_widget_size_request (clist->vscrollbar,
-                              &clist->vscrollbar->requisition);
-
-      requisition->width += (clist->vscrollbar->requisition.width +
-                            SCROLLBAR_SPACING (clist));
-      requisition->height = MAX (requisition->height,
-                                clist->vscrollbar->requisition.height);
-    }
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_CLIST (object));
 
-  /* add the hscrollbar space */
-  if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
-      GTK_WIDGET_VISIBLE (clist->hscrollbar))
-    {
-      gtk_widget_size_request (clist->hscrollbar,
-                              &clist->hscrollbar->requisition);
+  clist = GTK_CLIST (object);
 
-      requisition->height += (clist->hscrollbar->requisition.height +
-                             SCROLLBAR_SPACING (clist));
-      requisition->width = MAX (clist->hscrollbar->requisition.width, 
-                               requisition->width - 
-                               clist->vscrollbar->requisition.width);
+  columns_delete (clist);
 
-    }
+  g_mem_chunk_destroy (clist->cell_mem_chunk);
+  g_mem_chunk_destroy (clist->row_mem_chunk);
 
-  requisition->width += (widget->style->klass->xthickness * 2 +
-                        GTK_CONTAINER (widget)->border_width * 2);
-  requisition->height += (widget->style->klass->ythickness * 2 +
-                         GTK_CONTAINER (widget)->border_width * 2);
+  if (GTK_OBJECT_CLASS (parent_class)->finalize)
+    (*GTK_OBJECT_CLASS (parent_class)->finalize) (object);
 }
 
+/* GTKWIDGET
+ *   gtk_clist_realize
+ *   gtk_clist_unrealize
+ *   gtk_clist_map
+ *   gtk_clist_unmap
+ *   gtk_clist_draw
+ *   gtk_clist_expose
+ *   gtk_clist_style_set
+ *   gtk_clist_key_press
+ *   gtk_clist_button_press
+ *   gtk_clist_button_release
+ *   gtk_clist_motion
+ *   gtk_clist_size_request
+ *   gtk_clist_size_allocate
+ */
 static void
-gtk_clist_size_allocate (GtkWidget * widget,
-                        GtkAllocation * allocation)
+gtk_clist_realize (GtkWidget *widget)
 {
   GtkCList *clist;
-  GtkAllocation clist_allocation;
-  GtkAllocation child_allocation;
-  gint i, vscrollbar_vis, hscrollbar_vis;
+  GdkWindowAttr attributes;
+  GdkGCValues values;
+  GtkCListRow *clist_row;
+  GList *list;
+  gint attributes_mask;
   gint border_width;
+  gint i;
+  gint j;
 
   g_return_if_fail (widget != NULL);
   g_return_if_fail (GTK_IS_CLIST (widget));
-  g_return_if_fail (allocation != NULL);
 
   clist = GTK_CLIST (widget);
-  widget->allocation = *allocation;
-  border_width = GTK_CONTAINER (widget)->border_width;
 
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      gdk_window_move_resize (widget->window,
-                             allocation->x + border_width,
-                             allocation->y + border_width,
-                             allocation->width - border_width * 2,
-                             allocation->height - border_width * 2);
-    }
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
-  /* use internal allocation structure for all the math
-   * because it's easier than always subtracting the container
-   * border width */
-  clist->internal_allocation.x = 0;
-  clist->internal_allocation.y = 0;
-  clist->internal_allocation.width = MAX (1, allocation->width -
-                                         border_width * 2);
-  clist->internal_allocation.height = MAX (1, allocation->height -
-                                          border_width * 2);
-       
-  /* allocate clist window assuming no scrollbars */
-  clist_allocation.x = (clist->internal_allocation.x +
-                       widget->style->klass->xthickness);
-  clist_allocation.y = (clist->internal_allocation.y +
-                       widget->style->klass->ythickness +
-                       clist->column_title_area.height);
-  clist_allocation.width = MAX (1, clist->internal_allocation.width - 
-                               (2 * widget->style->klass->xthickness));
-  clist_allocation.height = MAX (1, clist->internal_allocation.height -
-                                (2 * widget->style->klass->ythickness) -
-                                clist->column_title_area.height);
+  border_width = GTK_CONTAINER (widget)->border_width;
   
-  /* 
-   * here's where we decide to show/not show the scrollbars
-   */
-  vscrollbar_vis = 0;
-  hscrollbar_vis = 0;
-  
-  for (i = 0; i <= 1; i++)
-    {
-      if (LIST_HEIGHT (clist) <= clist_allocation.height &&
-         clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
-       {
-         vscrollbar_vis = 0;
-       }
-      else if (!vscrollbar_vis)
-       {
-         vscrollbar_vis = 1;
-         clist_allocation.width = MAX (1, clist_allocation.width - 
-                                       (clist->vscrollbar->requisition.width +
-                                        SCROLLBAR_SPACING (clist)));
-       }  
-      
-      if (LIST_WIDTH (clist) <= clist_allocation.width &&
-         clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
-       {
-         hscrollbar_vis = 0;
-       }
-      else if (!hscrollbar_vis)
-       {
-         hscrollbar_vis = 1;
-         clist_allocation.height = MAX (1, clist_allocation.height - 
-                                        (clist->hscrollbar->requisition.height
-                                         + SCROLLBAR_SPACING (clist)));
-       }  
-    }
-  
-  clist->clist_window_width = clist_allocation.width;
-  clist->clist_window_height = clist_allocation.height;
-  
-  if (GTK_WIDGET_REALIZED (widget))
-    {
-      gdk_window_move_resize (clist->clist_window,
-                             clist_allocation.x,
-                             clist_allocation.y,
-                             clist_allocation.width,
-                             clist_allocation.height);
-    }
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - border_width * 2;
+  attributes.height = widget->allocation.height - border_width * 2;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.event_mask = gtk_widget_get_events (widget);
+  attributes.event_mask |= (GDK_EXPOSURE_MASK |
+                           GDK_BUTTON_PRESS_MASK |
+                           GDK_BUTTON_RELEASE_MASK |
+                           GDK_KEY_PRESS_MASK |
+                           GDK_KEY_RELEASE_MASK);
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+  /* main window */
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                  &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, clist);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+
+  /* column-title window */
+
+  attributes.x = clist->column_title_area.x;
+  attributes.y = clist->column_title_area.y;
+  attributes.width = clist->column_title_area.width;
+  attributes.height = clist->column_title_area.height;
   
-  /* position the window which holds the column title buttons */
-  clist->column_title_area.x = widget->style->klass->xthickness;
-  clist->column_title_area.y = widget->style->klass->ythickness;
-  clist->column_title_area.width = clist_allocation.width;
+  clist->title_window = gdk_window_new (widget->window, &attributes,
+                                       attributes_mask);
+  gdk_window_set_user_data (clist->title_window, clist);
+
+  gtk_style_set_background (widget->style, clist->title_window,
+                           GTK_STATE_SELECTED);
+  gdk_window_show (clist->title_window);
+
+  /* set things up so column buttons are drawn in title window */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].button)
+      gtk_widget_set_parent_window (clist->column[i].button,
+                                   clist->title_window);
+
+  /* clist-window */
+  attributes.x = (clist->internal_allocation.x +
+                 widget->style->klass->xthickness);
+  attributes.y = (clist->internal_allocation.y +
+                 widget->style->klass->ythickness +
+                 clist->column_title_area.height);
+  attributes.width = clist->clist_window_width;
+  attributes.height = clist->clist_window_height;
   
-  if (GTK_WIDGET_REALIZED (widget))
+  clist->clist_window = gdk_window_new (widget->window, &attributes,
+                                       attributes_mask);
+  gdk_window_set_user_data (clist->clist_window, clist);
+
+  gdk_window_set_background (clist->clist_window,
+                            &widget->style->bg[GTK_STATE_PRELIGHT]);
+  gdk_window_show (clist->clist_window);
+  gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
+                      &clist->clist_window_height);
+
+  /* create resize windows */
+  attributes.wclass = GDK_INPUT_ONLY;
+  attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
+                          GDK_BUTTON_RELEASE_MASK |
+                          GDK_POINTER_MOTION_MASK |
+                          GDK_POINTER_MOTION_HINT_MASK |
+                          GDK_KEY_PRESS_MASK);
+  attributes_mask = GDK_WA_CURSOR;
+  attributes.cursor = gdk_cursor_new (GDK_SB_H_DOUBLE_ARROW);
+  clist->cursor_drag = attributes.cursor;
+
+  attributes.x =  LIST_WIDTH (clist) + 1;
+  attributes.y = 0;
+  attributes.width = 0;
+  attributes.height = 0;
+
+  for (i = 0; i < clist->columns; i++)
     {
-      gdk_window_move_resize (clist->title_window,
-                             clist->column_title_area.x,
-                             clist->column_title_area.y,
-                             clist->column_title_area.width,
-                             clist->column_title_area.height);
+      clist->column[i].window = gdk_window_new (clist->title_window,
+                                               &attributes, attributes_mask);
+      gdk_window_set_user_data (clist->column[i].window, clist);
     }
-  
-  /* column button allocation */
-  size_allocate_columns (clist);
+
+  /* This is slightly less efficient than creating them with the
+   * right size to begin with, but easier
+   */
   size_allocate_title_buttons (clist);
 
-  adjust_scrollbars (clist);
-  
-  /* allocate the vscrollbar */
-  if (vscrollbar_vis)
-    {
-      if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
-       gtk_widget_show (clist->vscrollbar);
-      
-      child_allocation.x = (clist->internal_allocation.x + 
-                           clist->internal_allocation.width -
-                           clist->vscrollbar->requisition.width);
-      child_allocation.y = clist->internal_allocation.y;
-      child_allocation.width = clist->vscrollbar->requisition.width;
-      child_allocation.height = MAX (1, clist->internal_allocation.height -
-                                    (hscrollbar_vis ?
-                                     (clist->hscrollbar->requisition.height +
-                                      SCROLLBAR_SPACING (clist)) : 0));
-      gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
-    }
-  else
-    {
-      if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
-       gtk_widget_hide (clist->vscrollbar);
-    }
+  /* GCs */
+  clist->fg_gc = gdk_gc_new (widget->window);
+  clist->bg_gc = gdk_gc_new (widget->window);
   
-  if (hscrollbar_vis)
+  /* We'll use this gc to do scrolling as well */
+  gdk_gc_set_exposures (clist->fg_gc, TRUE);
+
+  values.foreground = widget->style->white;
+  values.function = GDK_XOR;
+  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+  clist->xor_gc = gdk_gc_new_with_values (widget->window,
+                                         &values,
+                                         GDK_GC_FOREGROUND |
+                                         GDK_GC_FUNCTION |
+                                         GDK_GC_SUBWINDOW);
+
+  /* attach optional row/cell styles, allocate foreground/background colors */
+  list = clist->row_list;
+  for (i = 0; i < clist->rows; i++)
     {
-      if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
-       gtk_widget_show (clist->hscrollbar);
-      
-      child_allocation.x = clist->internal_allocation.x;
-      child_allocation.y = (clist->internal_allocation.y +
-                           clist->internal_allocation.height -
-                           clist->hscrollbar->requisition.height);
-      child_allocation.width = MAX (1, clist->internal_allocation.width -
-                                   (vscrollbar_vis ?
-                                    (clist->vscrollbar->requisition.width +
-                                     SCROLLBAR_SPACING (clist)) : 0));
-      child_allocation.height = clist->hscrollbar->requisition.height;
+      clist_row = list->data;
+      list = list->next;
+
+      if (clist_row->style)
+       clist_row->style = gtk_style_attach (clist_row->style,
+                                            clist->clist_window);
+
+      if (clist_row->fg_set || clist_row->bg_set)
+       {
+         GdkColormap *colormap;
+
+         colormap = gtk_widget_get_colormap (widget);
+         if (clist_row->fg_set)
+           gdk_color_alloc (colormap, &clist_row->foreground);
+         if (clist_row->bg_set)
+           gdk_color_alloc (colormap, &clist_row->background);
+       }
       
-      gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
-    }
-  else
-    {
-      if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
-       gtk_widget_hide (clist->hscrollbar);
+      for (j = 0; j < clist->columns; j++)
+       if  (clist_row->cell[j].style)
+         clist_row->cell[j].style =
+           gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
     }
-
-  /* set the vscrollbar adjustments */
-  adjust_scrollbars (clist);
 }
 
-/* 
- * GTKCONTAINER
- *   gtk_clist_forall
- */
 static void
-gtk_clist_forall (GtkContainer *container,
-                 gboolean      include_internals,
-                 GtkCallback   callback,
-                 gpointer      callback_data)
+gtk_clist_unrealize (GtkWidget *widget)
 {
+  gint i;
   GtkCList *clist;
 
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_CLIST (container));
-  g_return_if_fail (callback != NULL);
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
 
-  clist = GTK_CLIST (container);
-      
-  if (include_internals)
+  clist = GTK_CLIST (widget);
+
+  GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+
+  /* detach optional row/cell styles */
+
+  if (GTK_WIDGET_REALIZED (widget))
     {
-      guint i;
-      
-      /* callback for the column buttons */
-      for (i = 0; i < clist->columns; i++)
-       if (clist->column[i].button)
-         (*callback) (clist->column[i].button, callback_data);
-      
-      /* callbacks for the scrollbars */
-      if (clist->vscrollbar)
-       (*callback) (clist->vscrollbar, callback_data);
-      if (clist->hscrollbar)
-       (*callback) (clist->hscrollbar, callback_data);
-    }
-}
-
-/*
- * DRAWING
- *   get_cell_style
- *   draw_cell_pixmap
- *   draw_row
- *   draw_rows
- */
-
-static void
-get_cell_style (GtkCList     *clist,
-               GtkCListRow  *clist_row,
-               gint          state,
-               gint          column,
-               GtkStyle    **style,
-               GdkGC       **fg_gc,
-               GdkGC       **bg_gc)
-{
-  if (clist_row->cell[column].style)
-    {
-      if (style)
-       *style = clist_row->cell[column].style;
-      if (fg_gc)
-       *fg_gc = clist_row->cell[column].style->fg_gc[state];
-      if (bg_gc)
-       *bg_gc = clist_row->cell[column].style->bg_gc[state];
-    }
-  else if (clist_row->style)
-    {
-      if (style)
-       *style = clist_row->style;
-      if (fg_gc)
-       *fg_gc = clist_row->style->fg_gc[state];
-      if (bg_gc)
-       *bg_gc = clist_row->style->bg_gc[state];
-    }
-  else
-    {
-      if (style)
-       *style = GTK_WIDGET (clist)->style;
-      if (fg_gc)
-       *fg_gc = GTK_WIDGET (clist)->style->fg_gc[state];
-      if (bg_gc)
-       *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
+      GtkCListRow *clist_row;
+      GList *list;
+      gint j;
 
-      if (state != GTK_STATE_SELECTED)
+      list = clist->row_list;
+      for (i = 0; i < clist->rows; i++)
        {
-         if (fg_gc && clist_row->fg_set)
-           *fg_gc = clist->fg_gc;
-         if (bg_gc && clist_row->bg_set)
-           *bg_gc = clist->bg_gc;
+         clist_row = list->data;
+         list = list->next;
+
+         if (clist_row->style)
+           gtk_style_detach (clist_row->style);
+         for (j = 0; j < clist->columns; j++)
+           if  (clist_row->cell[j].style)
+             gtk_style_detach (clist_row->cell[j].style);
        }
     }
-}
 
-static gint
-draw_cell_pixmap (GdkWindow    *window,
-                 GdkRectangle *clip_rectangle,
-                 GdkGC        *fg_gc,
-                 GdkPixmap    *pixmap,
-                 GdkBitmap    *mask,
-                 gint          x,
-                 gint          y,
-                 gint          width,
-                 gint          height)
-{
-  gint xsrc = 0;
-  gint ysrc = 0;
+  gdk_cursor_destroy (clist->cursor_drag);
+  gdk_gc_destroy (clist->xor_gc);
+  gdk_gc_destroy (clist->fg_gc);
+  gdk_gc_destroy (clist->bg_gc);
 
-  if (mask)
-    {
-      gdk_gc_set_clip_mask (fg_gc, mask);
-      gdk_gc_set_clip_origin (fg_gc, x, y);
-    }
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].window)
+      {
+       gdk_window_set_user_data (clist->column[i].window, NULL);
+       gdk_window_destroy (clist->column[i].window);
+       clist->column[i].window = NULL;
+      }
 
-  if (x < clip_rectangle->x)
-    {
-      xsrc = clip_rectangle->x - x;
-      width -= xsrc;
-      x = clip_rectangle->x;
-    }
-  if (x + width > clip_rectangle->x + clip_rectangle->width)
-    width = clip_rectangle->x + clip_rectangle->width - x;
+  gdk_window_set_user_data (clist->clist_window, NULL);
+  gdk_window_destroy (clist->clist_window);
+  clist->clist_window = NULL;
 
-  if (y < clip_rectangle->y)
-    {
-      ysrc = clip_rectangle->y - y;
-      height -= ysrc;
-      y = clip_rectangle->y;
-    }
-  if (y + height > clip_rectangle->y + clip_rectangle->height)
-    height = clip_rectangle->y + clip_rectangle->height - y;
+  gdk_window_set_user_data (clist->title_window, NULL);
+  gdk_window_destroy (clist->title_window);
+  clist->title_window = NULL;
 
-  gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
-  gdk_gc_set_clip_origin (fg_gc, 0, 0);
+  clist->cursor_drag = NULL;
+  clist->xor_gc = NULL;
+  clist->fg_gc = NULL;
+  clist->bg_gc = NULL;
 
-  return x + MAX (width, 0);
+  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
+    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 }
 
 static void
-draw_row (GtkCList * clist,
-         GdkRectangle * area,
-         gint row,
-         GtkCListRow * clist_row)
+gtk_clist_map (GtkWidget *widget)
 {
-  GtkWidget *widget;
-  GdkRectangle *rect;
-  GdkRectangle row_rectangle;
-  GdkRectangle cell_rectangle;
-  GdkRectangle clip_rectangle;
-  GdkRectangle intersect_rectangle;
-  gint state;
   gint i;
+  GtkCList *clist;
 
-  g_return_if_fail (clist != NULL);
-
-  /* bail now if we arn't drawable yet */
-  if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
-    return;
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
 
-  widget = GTK_WIDGET (clist);
+  clist = GTK_CLIST (widget);
 
-  /* if the function is passed the pointer to the row instead of null,
-   * it avoids this expensive lookup */
-  if (!clist_row)
-    clist_row = (g_list_nth (clist->row_list, row))->data;
+  if (!GTK_WIDGET_MAPPED (widget))
+    {
+      GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
 
-  /* rectangle of the entire row */
-  row_rectangle.x = 0;
-  row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
-  row_rectangle.width = clist->clist_window_width;
-  row_rectangle.height = clist->row_height;
+      gdk_window_show (widget->window);
+      gdk_window_show (clist->title_window);
+      gdk_window_show (clist->clist_window);
 
-  /* rectangle of the cell spacing above the row */
-  cell_rectangle.x = 0;
-  cell_rectangle.y = row_rectangle.y - CELL_SPACING;
-  cell_rectangle.width = row_rectangle.width;
-  cell_rectangle.height = CELL_SPACING;
+      /* map column buttons */
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button &&
+           GTK_WIDGET_VISIBLE (clist->column[i].button) &&
+           !GTK_WIDGET_MAPPED (clist->column[i].button))
+         gtk_widget_map (clist->column[i].button);
+      
+      /* map resize windows AFTER column buttons (above) */
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].window && clist->column[i].button)
+         gdk_window_show (clist->column[i].window);
+       
+      /* map vscrollbars */
+      if (GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
+         !GTK_WIDGET_MAPPED (clist->vscrollbar))
+       gtk_widget_map (clist->vscrollbar);
 
-  /* rectangle used to clip drawing operations, it's y and height
-   * positions only need to be set once, so we set them once here. 
-   * the x and width are set withing the drawing loop below once per
-   * column */
-  clip_rectangle.y = row_rectangle.y;
-  clip_rectangle.height = row_rectangle.height;
+      if (GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
+         !GTK_WIDGET_MAPPED (clist->hscrollbar))
+       gtk_widget_map (clist->hscrollbar);
 
-  if (clist_row->state == GTK_STATE_NORMAL)
-    {
-      state = GTK_STATE_PRELIGHT;
-      if (clist_row->fg_set)
-       gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
-      if (clist_row->bg_set)
-       gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
+      /* unfreeze the list */
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
     }
-  else
-    state = clist_row->state;
-
-  /* draw the cell borders and background */
-  if (area)
-    {
-      rect = &intersect_rectangle;
-      if (gdk_rectangle_intersect (area, &cell_rectangle,
-                                  &intersect_rectangle))
-       gdk_draw_rectangle (clist->clist_window,
-                           widget->style->base_gc[GTK_STATE_NORMAL],
-                           TRUE,
-                           intersect_rectangle.x,
-                           intersect_rectangle.y,
-                           intersect_rectangle.width,
-                           intersect_rectangle.height);
+}
 
-      /* the last row has to clear it's bottom cell spacing too */
-      if (clist_row == clist->row_list_end->data)
-       {
-         cell_rectangle.y += clist->row_height + CELL_SPACING;
+static void
+gtk_clist_unmap (GtkWidget *widget)
+{
+  gint i;
+  GtkCList *clist;
 
-         if (gdk_rectangle_intersect (area, &cell_rectangle,
-                                      &intersect_rectangle))
-           gdk_draw_rectangle (clist->clist_window,
-                               widget->style->base_gc[GTK_STATE_NORMAL],
-                               TRUE,
-                               intersect_rectangle.x,
-                               intersect_rectangle.y,
-                               intersect_rectangle.width,
-                               intersect_rectangle.height);
-       }
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
 
-      if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
-       return;
+  clist = GTK_CLIST (widget);
 
-    }
-  else
+  if (GTK_WIDGET_MAPPED (widget))
     {
-      rect = &clip_rectangle;
-      gdk_draw_rectangle (clist->clist_window,
-                         widget->style->base_gc[GTK_STATE_NORMAL],
-                         TRUE,
-                         cell_rectangle.x,
-                         cell_rectangle.y,
-                         cell_rectangle.width,
-                         cell_rectangle.height);
+      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
-      /* the last row has to clear it's bottom cell spacing too */
-      if (clist_row == clist->row_list_end->data)
-       {
-         cell_rectangle.y += clist->row_height + CELL_SPACING;
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].window)
+         gdk_window_hide (clist->column[i].window);
 
-         gdk_draw_rectangle (clist->clist_window,
-                             widget->style->base_gc[GTK_STATE_NORMAL],
-                             TRUE,
-                             cell_rectangle.x,
-                             cell_rectangle.y,
-                             cell_rectangle.width,
-                             cell_rectangle.height);     
-       }         
-    }
-  
-  /* iterate and draw all the columns (row cells) and draw their contents */
-  for (i = 0; i < clist->columns; i++)
-    {
-      GtkStyle *style;
-      GdkGC *fg_gc;
-      GdkGC *bg_gc;
+      gdk_window_hide (clist->clist_window);
+      gdk_window_hide (clist->title_window);
+      gdk_window_hide (widget->window);
 
-      gint width;
-      gint height;
-      gint pixmap_width;
-      gint offset = 0;
-      gint row_center_offset;
+      /* unmap scrollbars */
+      if (GTK_WIDGET_MAPPED (clist->vscrollbar))
+       gtk_widget_unmap (clist->vscrollbar);
 
-      if (!clist->column[i].visible)
-       continue;
+      if (GTK_WIDGET_MAPPED (clist->hscrollbar))
+       gtk_widget_unmap (clist->hscrollbar);
 
-      get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
+      /* unmap column buttons */
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button &&
+           GTK_WIDGET_MAPPED (clist->column[i].button))
+         gtk_widget_unmap (clist->column[i].button);
 
-      clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
-      clip_rectangle.width = clist->column[i].area.width;
+      /* freeze the list */
+      GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
+    }
+}
 
-      /* calculate clipping region clipping region */
-      clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
-      clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
-                              (i + 1 == clist->columns) * CELL_SPACING);
-      
-      if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
-                                           &intersect_rectangle))
-       continue;
+static void
+gtk_clist_draw (GtkWidget    *widget,
+               GdkRectangle *area)
+{
+  GtkCList *clist;
+  gint border_width;
+  GdkRectangle child_area;
+  int i;
 
-      gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
-                         rect->x, rect->y, rect->width, rect->height);
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (area != NULL);
 
-      clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
-      clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
-                              (i + 1 == clist->columns) * CELL_SPACING);
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      clist = GTK_CLIST (widget);
+      border_width = GTK_CONTAINER (widget)->border_width;
 
-      /* calculate real width for column justification */
-      pixmap_width = 0;
-      offset = 0;
-      switch (clist_row->cell[i].type)
+      gdk_window_clear_area (widget->window,
+                            area->x - border_width, 
+                            area->y - border_width,
+                            area->width, area->height);
+
+      /* draw list shadow/border */
+      gtk_draw_shadow (widget->style, widget->window,
+                      GTK_STATE_NORMAL, clist->shadow_type,
+                      0, 0, 
+                      clist->clist_window_width +
+                      (2 * widget->style->klass->xthickness),
+                      clist->clist_window_height +
+                      (2 * widget->style->klass->ythickness) +
+                      clist->column_title_area.height);
+
+      gdk_window_clear_area (clist->clist_window, 0, 0, -1, -1);
+      draw_rows (clist, NULL);
+
+      for (i = 0; i < clist->columns; i++)
        {
-       case GTK_CELL_TEXT:
-         width = gdk_string_width (style->font,
-                                   GTK_CELL_TEXT (clist_row->cell[i])->text);
-         break;
-       case GTK_CELL_PIXMAP:
-         gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
-                              &pixmap_width, &height);
-         width = pixmap_width;
-         break;
-       case GTK_CELL_PIXTEXT:
-         gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
-                              &pixmap_width, &height);
-         width = (pixmap_width +
-                  GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
-                  gdk_string_width (style->font,
-                                    GTK_CELL_PIXTEXT
-                                    (clist_row->cell[i])->text));
-         break;
-       default:
-         continue;
-         break;
+         if (!clist->column[i].visible)
+           continue;
+         if (gtk_widget_intersect(clist->column[i].button, area, &child_area))
+           gtk_widget_draw (clist->column[i].button, &child_area);
        }
+    }
+}
 
-      switch (clist->column[i].justification)
-       {
-       case GTK_JUSTIFY_LEFT:
-         offset = clip_rectangle.x + clist_row->cell[i].horizontal;
-         break;
-       case GTK_JUSTIFY_RIGHT:
-         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
-                   clip_rectangle.width - width);
-         break;
-       case GTK_JUSTIFY_CENTER:
-       case GTK_JUSTIFY_FILL:
-         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
-                   (clip_rectangle.width / 2) - (width / 2));
-         break;
-       };
+static gint
+gtk_clist_expose (GtkWidget      *widget,
+                 GdkEventExpose *event)
+{
+  GtkCList *clist;
 
-      /* Draw Text and/or Pixmap */
-      switch (clist_row->cell[i].type)
-       {
-       case GTK_CELL_PIXMAP:
-         draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
-                           GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
-                           GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
-                           offset,
-                           clip_rectangle.y + clist_row->cell[i].vertical +
-                           (clip_rectangle.height - height) / 2,
-                           pixmap_width, height);
-         break;
-       case GTK_CELL_PIXTEXT:
-         offset =
-           draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
-                             GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
-                             GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
-                             offset,
-                             clip_rectangle.y + clist_row->cell[i].vertical+
-                             (clip_rectangle.height - height) / 2,
-                             pixmap_width, height);
-         offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
-       case GTK_CELL_TEXT:
-         if (style != GTK_WIDGET (clist)->style)
-           row_center_offset = (((clist->row_height - style->font->ascent -
-                                 style->font->descent - 1) / 2) + 1.5 +
-                                style->font->ascent);
-         else
-           row_center_offset = clist->row_center_offset;
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
 
-         gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
-         gdk_draw_string (clist->clist_window, style->font, fg_gc,
-                          offset,
-                          row_rectangle.y + row_center_offset + 
-                          clist_row->cell[i].vertical,
-                          (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
-                          GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
-                          GTK_CELL_TEXT (clist_row->cell[i])->text);
-         gdk_gc_set_clip_rectangle (fg_gc, NULL);
-         break;
-       default:
-         break;
-       }
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      clist = GTK_CLIST (widget);
+
+      /* draw border */
+      if (event->window == widget->window)
+       gtk_draw_shadow (widget->style, widget->window,
+                        GTK_STATE_NORMAL, clist->shadow_type,
+                        0, 0,
+                        clist->clist_window_width +
+                        (2 * widget->style->klass->xthickness),
+                        clist->clist_window_height +
+                        (2 * widget->style->klass->ythickness) +
+                        clist->column_title_area.height);
+
+      /* exposure events on the list */
+      if (event->window == clist->clist_window)
+       draw_rows (clist, &event->area);
     }
 
-  /* draw focus rectangle */
-  if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
+  return FALSE;
+}
+
+static void
+gtk_clist_style_set (GtkWidget *widget,
+                    GtkStyle  *previous_style)
+{
+  GtkCList *clist;
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  if (GTK_WIDGET_CLASS (parent_class)->style_set)
+    (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
+
+  clist = GTK_CLIST (widget);
+
+  /* Fill in data after widget has correct style */
+
+  /* text properties */
+  if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
     {
-      if (!area)
-       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
-                           row_rectangle.x, row_rectangle.y,
-                           row_rectangle.width - 1, row_rectangle.height - 1);
-      else if (gdk_rectangle_intersect (area, &row_rectangle,
-                                       &intersect_rectangle))
-       {
-         gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
-         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
-                             row_rectangle.x, row_rectangle.y,
-                             row_rectangle.width - 1,
-                             row_rectangle.height - 1);
-         gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
-       }
+      clist->row_height = (widget->style->font->ascent +
+                          widget->style->font->descent + 1);
+      clist->row_center_offset = widget->style->font->ascent + 1.5;
+    }
+  else
+    clist->row_center_offset = 1.5 + (clist->row_height +
+                                     widget->style->font->ascent -
+                                     widget->style->font->descent - 1) / 2;
+
+  /* Column widths */
+  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      gint width;
+      gint i;
+
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           width = gtk_clist_optimal_column_width (clist, i);
+           if (width != clist->column[i].width)
+             gtk_clist_set_column_width (clist, i, width);
+         }
     }
 }
 
-static void
-draw_rows (GtkCList * clist,
-          GdkRectangle * area)
-{
-  GList *list;
-  GtkCListRow *clist_row;
-  int i, first_row, last_row;
+static gint
+gtk_clist_key_press (GtkWidget   *widget,
+                    GdkEventKey *event)
+{
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
+      GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
+    return TRUE;
+
+  switch (event->keyval)
+    {
+    case GDK_Tab:
+    case GDK_ISO_Left_Tab:
+      if (event->state & GDK_SHIFT_MASK)
+       return gtk_container_focus (GTK_CONTAINER (widget),
+                                   GTK_DIR_TAB_BACKWARD);
+      else
+       return gtk_container_focus (GTK_CONTAINER (widget),
+                                   GTK_DIR_TAB_FORWARD);
+    default:
+      break;
+    }
+  return FALSE;
+}
+
+static gint
+gtk_clist_button_press (GtkWidget      *widget,
+                       GdkEventButton *event)
+{
+  gint i;
+  GtkCList *clist;
+  gint x;
+  gint y;
+  gint row;
+  gint column;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  clist = GTK_CLIST (widget);
+
+  /* we don't handle button 2 and 3 */
+  if (event->button != 1)
+    return FALSE;
+  
+  /* selections on the list */
+  if (event->window == clist->clist_window)
+    {
+      x = event->x;
+      y = event->y;
+
+      if (get_selection_info (clist, x, y, &row, &column))
+       {
+         gint old_row = clist->focus_row;
+
+         if (clist->focus_row == -1)
+           old_row = row;
+
+         if (event->type == GDK_BUTTON_PRESS)
+           {
+             GTK_CLIST_SET_FLAG (clist, CLIST_DRAG_SELECTION);
+             gdk_pointer_grab (clist->clist_window, FALSE,
+                               GDK_POINTER_MOTION_HINT_MASK |
+                               GDK_BUTTON1_MOTION_MASK |
+                               GDK_BUTTON_RELEASE_MASK,
+                               NULL, NULL, event->time);
+             gtk_grab_add (widget);
+           }
+         else if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (widget))
+           {
+             GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
+             gtk_grab_remove (widget);
+             gdk_pointer_ungrab (event->time);
+           }
+
+         if (GTK_CLIST_ADD_MODE (clist))
+           {
+             GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
+             if (GTK_WIDGET_HAS_FOCUS (widget))
+               {
+                 gtk_clist_draw_focus (widget);
+                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                             GDK_LINE_SOLID, 0, 0);
+                 clist->focus_row = row;
+                 gtk_clist_draw_focus (widget);
+               }
+             else
+               {
+                 gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                             GDK_LINE_SOLID, 0, 0);
+                 clist->focus_row = row;
+               }
+           }
+         else if (row != clist->focus_row)
+           {
+             if (GTK_WIDGET_HAS_FOCUS (widget))
+               {
+                 gtk_clist_draw_focus (widget);
+                 clist->focus_row = row;
+                 gtk_clist_draw_focus (widget);
+               }
+             else
+               clist->focus_row = row;
+           }
+
+         if (!GTK_WIDGET_HAS_FOCUS (widget))
+           gtk_widget_grab_focus (widget);
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+         switch (clist->selection_mode)
+           {
+           case GTK_SELECTION_SINGLE:
+           case GTK_SELECTION_MULTIPLE:
+             if (event->type != GDK_BUTTON_PRESS)
+               gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                                row, column, event);
+             else
+               clist->anchor = row;
+             break;
+           case GTK_SELECTION_BROWSE:
+             gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                              row, column, event);
+             break;
+           case GTK_SELECTION_EXTENDED:
+             if (event->type != GDK_BUTTON_PRESS)
+               {
+                 if (clist->anchor != -1)
+                   {
+                     update_extended_selection (clist, clist->focus_row);
+                     GTK_CLIST_CLASS_FW (clist)->resync_selection
+                       (clist, (GdkEvent *) event);
+                   }
+                 gtk_signal_emit (GTK_OBJECT (clist),
+                                  clist_signals[SELECT_ROW],
+                                  row, column, event);
+                 break;
+               }
+             
+             if (event->state & GDK_CONTROL_MASK)
+               {
+                 if (event->state & GDK_SHIFT_MASK)
+                   {
+                     if (clist->anchor < 0)
+                       {
+                         g_list_free (clist->undo_selection);
+                         g_list_free (clist->undo_unselection);
+                         clist->undo_selection = NULL;
+                         clist->undo_unselection = NULL;
+                         clist->anchor = old_row;
+                         clist->drag_pos = old_row;
+                         clist->undo_anchor = old_row;
+                       }
+                     update_extended_selection (clist, clist->focus_row);
+                   }
+                 else
+                   {
+                     if (clist->anchor == -1)
+                       set_anchor (clist, TRUE, row, old_row);
+                     else
+                       update_extended_selection (clist, clist->focus_row);
+                   }
+                 break;
+               }
 
-  if (clist->row_height == 0 ||
-      !GTK_WIDGET_DRAWABLE (clist))
-    return;
+             if (event->state & GDK_SHIFT_MASK)
+               {
+                 set_anchor (clist, FALSE, old_row, old_row);
+                 update_extended_selection (clist, clist->focus_row);
+                 break;
+               }
 
-  if (area)
-    {
-      first_row = ROW_FROM_YPIXEL (clist, area->y);
-      last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
-    }
-  else
-    {
-      first_row = ROW_FROM_YPIXEL (clist, 0);
-      last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
+             if (clist->anchor == -1)
+               set_anchor (clist, FALSE, row, old_row);
+             else
+               update_extended_selection (clist, clist->focus_row);
+             break;
+           default:
+             break;
+           }
+       }
+
+      return FALSE;
     }
 
-  /* this is a small special case which exposes the bottom cell line
-   * on the last row -- it might go away if I change the wall the cell spacings
-   * are drawn */
-  if (clist->rows == first_row)
-    first_row--;
+  /* press on resize windows */
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].resizeable && clist->column[i].window &&
+       event->window == clist->column[i].window)
+      {
+       gdk_pointer_grab (clist->column[i].window, FALSE,
+                         GDK_POINTER_MOTION_HINT_MASK |
+                         GDK_BUTTON1_MOTION_MASK |
+                         GDK_BUTTON_RELEASE_MASK,
+                         NULL, NULL, event->time);
+       gtk_grab_add (widget);
+       GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
 
-  list = g_list_nth (clist->row_list, first_row);
-  i = first_row;
-  while (list)
-    {
-      clist_row = list->data;
-      list = list->next;
+       if (!GTK_WIDGET_HAS_FOCUS (widget))
+         gtk_widget_grab_focus (widget);
 
-      if (i > last_row)
-       return;
+       clist->drag_pos = i;
+       clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
+                        clist->column[i].area.width + CELL_SPACING);
 
-      GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
-      i++;
-    }
+       if (GTK_CLIST_ADD_MODE (clist))
+         gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
+       draw_xor_line (clist);
 
-  if (!area)
-    gdk_window_clear_area (clist->clist_window, 0, ROW_TOP_YPIXEL (clist, i), -1, -1);
+       return FALSE;
+      }
+  return FALSE;
 }
 
-/*
- * SIZE ALLOCATION
- *   size_allocate_title_buttons
- *   size_allocate_columns
- */
-static void
-size_allocate_title_buttons (GtkCList * clist)
+static gint
+gtk_clist_button_release (GtkWidget      *widget,
+                         GdkEventButton *event)
 {
-  GtkAllocation button_allocation;
-  gint last_column;
-  gint last_button = 0;
-  gint i;
+  GtkCList *clist;
 
-  if (!GTK_WIDGET_REALIZED (clist))
-    return;
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
 
-  button_allocation.x = clist->hoffset;
-  button_allocation.y = 0;
-  button_allocation.width = 0;
-  button_allocation.height = clist->column_title_area.height;
+  clist = GTK_CLIST (widget);
 
-  /* find last visible column */
-  for (last_column = clist->columns - 1; last_column >= 0; last_column--)
-    if (clist->column[last_column].visible)
-      break;
+  /* we don't handle button 2 and 3 */
+  if (event->button != 1)
+    return FALSE;
 
-  for (i = 0; i < last_column; i++)
+  /* release on resize windows */
+  if (GTK_CLIST_IN_DRAG (clist))
     {
-      if (!clist->column[i].visible)
-       {
-         last_button = i + 1;
-         gdk_window_hide (clist->column[i].window);
-         continue;
-       }
+      gint width;
+      gint x;
+      gint i;
 
-      button_allocation.width += (clist->column[i].area.width +
-                                 CELL_SPACING + 2 * COLUMN_INSET);
+      i = clist->drag_pos;
+      clist->drag_pos = -1;
 
-      if (!clist->column[i + 1].button)
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
+      gtk_widget_get_pointer (widget, &x, NULL);
+      gtk_grab_remove (widget);
+      gdk_pointer_ungrab (event->time);
+
+      if (clist->x_drag >= 0)
+       draw_xor_line (clist);
+
+      if (GTK_CLIST_ADD_MODE (clist))
        {
-         gdk_window_hide (clist->column[i].window);
-         continue;
+         gdk_gc_set_line_attributes (clist->xor_gc, 1,
+                                     GDK_LINE_ON_OFF_DASH, 0, 0);
+         gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
        }
 
-      gtk_widget_size_allocate (clist->column[last_button].button,
-                               &button_allocation);
-      button_allocation.x += button_allocation.width;
-      button_allocation.width = 0;
+      width = new_column_width (clist, i, &x);
+      gtk_clist_set_column_width (clist, i, width);
+      return FALSE;
+    }
 
-      if (clist->column[last_button].resizeable)
+  if (GTK_CLIST_DRAG_SELECTION (clist))
+    {
+      gint row;
+      gint column;
+
+      GTK_CLIST_UNSET_FLAG (clist, CLIST_DRAG_SELECTION);
+      gtk_grab_remove (widget);
+      gdk_pointer_ungrab (event->time);
+      if (clist->htimer)
        {
-         gdk_window_show (clist->column[last_button].window);
-         gdk_window_move_resize (clist->column[last_button].window,
-                                 button_allocation.x - (DRAG_WIDTH / 2), 
-                                 0, DRAG_WIDTH,
-                                 clist->column_title_area.height);
+         gtk_timeout_remove (clist->htimer);
+         clist->htimer = 0;
        }
-      else
-       gdk_window_hide (clist->column[last_button].window);
+      if (clist->vtimer)
+       {
+         gtk_timeout_remove (clist->vtimer);
+         clist->vtimer = 0;
+       }
+      switch (clist->selection_mode)
+       {
+       case GTK_SELECTION_EXTENDED:
+         if (!(event->state & GDK_SHIFT_MASK) ||
+             event->x < 0 || event->x >= clist->clist_window_width ||
+             event->y < 0 || event->y >= clist->clist_window_height)
+           GTK_CLIST_CLASS_FW (clist)->resync_selection
+             (clist, (GdkEvent *) event);
+         break;
 
-      last_button = i + 1;
+       case GTK_SELECTION_SINGLE:
+       case GTK_SELECTION_MULTIPLE:
+         if (get_selection_info (clist, event->x, event->y, &row, &column))
+           {
+             if (clist->anchor == clist->focus_row)
+               toggle_row (clist, row, column, (GdkEvent *) event);
+           }
+         clist->anchor = -1;
+         break;
+
+       default:
+         break;
+       }
     }
 
-  button_allocation.width += (clist->column[last_column].area.width +
-                             2 * (CELL_SPACING + COLUMN_INSET));
-  gtk_widget_size_allocate (clist->column[last_button].button,
-                           &button_allocation);
+  return FALSE;
+}
+
+static gint
+horizontal_timeout (GtkCList *clist)
+{
+  gint x, y;
+  GdkEventMotion event;
+  GdkModifierType mask;
+
+  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+
+  clist->htimer = 0;
+  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
+
+  event.is_hint = 0;
+  event.x = x;
+  event.y = y;
+  event.state = mask;
 
-  if (clist->column[last_button].resizeable)
-    {
-      button_allocation.x += button_allocation.width;
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
 
-      gdk_window_show (clist->column[last_button].window);
-      gdk_window_move_resize (clist->column[last_button].window,
-                             button_allocation.x - (DRAG_WIDTH / 2), 
-                             0, DRAG_WIDTH, clist->column_title_area.height);
-    }
-  else
-    gdk_window_hide (clist->column[last_button].window);
+  return FALSE;
 }
 
-static void
-size_allocate_columns (GtkCList * clist)
+static gint
+vertical_timeout (GtkCList *clist)
 {
-  gint xoffset = CELL_SPACING + COLUMN_INSET;
-  gint last_column;
-  gint width = 0;
-  gint i;
+  gint x, y;
+  GdkEventMotion event;
+  GdkModifierType mask;
 
-  /* find last visible column and calculate correct column width */
-  for (last_column = clist->columns - 1;
-       last_column >= 0 && !clist->column[last_column].visible; last_column--);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
 
-  if (last_column < 0)
-    return;
+  clist->vtimer = 0;
+  gdk_window_get_pointer (clist->clist_window, &x, &y, &mask);
 
-  for (i = 0; i < last_column; i++)
-    {
-      if (!clist->column[i].visible)
-       continue;
-      clist->column[i].area.x = xoffset;
-      clist->column[i].area.width = clist->column[i].width;
-      xoffset += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
-    }
+  event.is_hint = 0;
+  event.x = x;
+  event.y = y;
+  event.state = mask;
 
-  if (clist->column[i].width_set)
-    width = clist->column[i].width;
-  else if (clist->column[i].title)
-    width = gdk_string_width (GTK_WIDGET (clist)->style->font,
-                             clist->column[i].title);
+  gtk_clist_motion (GTK_WIDGET (clist), &event);
 
-  clist->column[i].area.x = xoffset;
-  clist->column[i].area.width = MAX (width,
-                                    clist->clist_window_width - xoffset -
-                                    (CELL_SPACING + COLUMN_INSET));
+  return FALSE;
 }
 
-/*
- * SELECTION
- *   select_row
- *   real_select_row
- *   real_unselect_row
- *   get_selection_info
- */
 static void
-toggle_row (GtkCList * clist,
-           gint row,
-           gint column,
-           GdkEvent * event)
+move_vertical (GtkCList *clist,
+              gint      row,
+              gfloat    align)
 {
-  GtkCListRow *clist_row;
+  gint y;
+  GtkAdjustment *adj;
 
-  switch (clist->selection_mode)
-    {
-    case GTK_SELECTION_EXTENDED:
-    case GTK_SELECTION_MULTIPLE:
-    case GTK_SELECTION_SINGLE:
+  adj = GTK_RANGE (clist->vscrollbar)->adjustment;
 
-      clist_row = g_list_nth (clist->row_list, row)->data;
-      if (clist_row->state == GTK_STATE_SELECTED)
-       {
-         unselect_row (clist, row, column, event);
-         return;
-       }
+  y = ROW_TOP_YPIXEL (clist, row) - clist->voffset;
+  
+  y = y - align * (clist->clist_window_height - clist->row_height)
+    + (2 * align - 1) * CELL_SPACING;
+  
+  if (y + adj->page_size > adj->upper)
+    adj->value = adj->upper - adj->page_size;
+  else
+    adj->value = y;
 
-    case GTK_SELECTION_BROWSE:
-      select_row (clist, row, column, event);
-      break;
-    }
+  gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
 }
 
 static void
-select_row (GtkCList * clist,
-           gint row,
-           gint column,
-           GdkEvent * event)
+move_horizontal (GtkCList *clist,
+                gint      diff)
 {
-  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                  row, column, event);
-}
+  gfloat upper;
+  GtkAdjustment *adj;
 
-static void
-unselect_row (GtkCList * clist,
-             gint row,
-             gint column,
-             GdkEvent * event)
-{
-  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
-                  row, column, event);
+  adj = GTK_RANGE (clist->hscrollbar)->adjustment;
+
+  adj->value += diff;
+
+  upper = adj->upper - adj->page_size;
+  adj->value = MIN (adj->value, upper);
+  adj->value = MAX (adj->value, 0.0);
+
+  gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
 }
 
-static void
-real_select_row (GtkCList * clist,
-                gint row,
-                gint column,
-                GdkEvent * event)
+static gint
+gtk_clist_motion (GtkWidget      *widget,
+                 GdkEventMotion *event)
 {
-  GtkCListRow *clist_row;
-  GList *list;
-  gint sel_row;
-  gboolean row_selected;
+  GtkCList *clist;
+  gint x;
+  gint y;
+  gint row;
+  gint new_width;
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
-  if (row < 0 || row > (clist->rows - 1))
-    return;
+  clist = GTK_CLIST (widget);
+  if (!(gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)))
+    return FALSE;
 
-  switch (clist->selection_mode)
+  if (GTK_CLIST_IN_DRAG (clist))
     {
-    case GTK_SELECTION_SINGLE:
-    case GTK_SELECTION_BROWSE:
+      if (event->is_hint || event->window != widget->window)
+       gtk_widget_get_pointer (widget, &x, NULL);
+      else
+       x = event->x;
+      
+      new_width = new_column_width (clist, clist->drag_pos, &x);
+      if (x != clist->x_drag)
+       {
+         /* x_drag < 0 indicates that the xor line is already invisible */
+         if (clist->x_drag >= 0)
+           draw_xor_line (clist);
 
-      row_selected = FALSE;
-      list = clist->selection;
+         clist->x_drag = x;
 
-      while (list)
+         if (clist->x_drag >= 0)
+           draw_xor_line (clist);
+       }
+
+      if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
+                           clist->column[clist->drag_pos].min_width + 1))
        {
-         sel_row = GPOINTER_TO_INT (list->data);
-         list = list->next;
+         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
+           gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
+         return FALSE;
+       }
+      if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
+         new_width >= clist->column[clist->drag_pos].max_width)
+       {
+         if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
+             clist->clist_window_width && x < 0)
+           move_horizontal (clist,
+                            COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
+                            new_width - clist->clist_window_width +
+                            COLUMN_INSET + CELL_SPACING);
+         return FALSE;
+       }
+    }
 
-         if (row == sel_row)
-           row_selected = TRUE;
+  if (event->is_hint || event->window != clist->clist_window)
+    gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
+
+  /* horizontal autoscrolling */
+  if (LIST_WIDTH (clist) > clist->clist_window_width &&
+      (x < 0 || x >= clist->clist_window_width))
+    {
+      if (clist->htimer)
+       return FALSE;
+
+      clist->htimer = gtk_timeout_add
+       (SCROLL_TIME, (GtkFunction) horizontal_timeout, clist);
+
+      if (!((x < 0 && GTK_RANGE (clist->hscrollbar)->adjustment->value == 0) ||
+           (x >= clist->clist_window_width &&
+            GTK_RANGE (clist->hscrollbar)->adjustment->value ==
+            LIST_WIDTH (clist) - clist->clist_window_width)))
+       {
+         if (x < 0)
+           move_horizontal (clist, -1 + (x/2));
          else
-           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
-                            sel_row, column, event);
+           move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
        }
-
-      if (row_selected)
-       return;
-      
-    default:
-      break;
     }
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  if (GTK_CLIST_IN_DRAG (clist))
+    return FALSE;
 
-  if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
-    return;
+  /* vertical autoscrolling */
+  row = ROW_FROM_YPIXEL (clist, y);
 
-  clist_row->state = GTK_STATE_SELECTED;
-  if (!clist->selection)
+  /* don't scroll on last pixel row if it's a cell spacing */
+  if (y == clist->clist_window_height-1 &&
+      y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
+    return FALSE;
+
+  if (LIST_HEIGHT (clist) > clist->clist_window_height &&
+      (y < 0 || y >= clist->clist_window_height))
     {
-      clist->selection = g_list_append (clist->selection,
-                                       GINT_TO_POINTER (row));
-      clist->selection_end = clist->selection;
+      if (clist->vtimer)
+       return FALSE;
+
+      clist->vtimer = gtk_timeout_add (SCROLL_TIME,
+                                      (GtkFunction) vertical_timeout, clist);
+
+      if (GTK_CLIST_DRAG_SELECTION (clist))
+       {
+         if ((y < 0 && clist->focus_row == 0) ||
+             (y >= clist->clist_window_height &&
+              clist->focus_row == clist->rows-1))
+           return FALSE;
+       }
+    }
+
+  row = CLAMP (row, 0, clist->rows - 1);
+
+  if (GTK_CLIST_DRAG_SELECTION (clist))
+    {
+      if (row == clist->focus_row)
+       return FALSE;
+
+      gtk_clist_draw_focus (widget);
+      clist->focus_row = row;
+      gtk_clist_draw_focus (widget);
+
+      switch (clist->selection_mode)
+       {
+       case GTK_SELECTION_BROWSE:
+         gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                          clist->focus_row, -1, event);
+         break;
+       case GTK_SELECTION_EXTENDED:
+         update_extended_selection (clist, clist->focus_row);
+         break;
+       default:
+         break;
+       }
     }
-  else
-    clist->selection_end = 
-      g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
   
-  if (!GTK_CLIST_FROZEN (clist)
-      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
-    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+  if (ROW_TOP_YPIXEL(clist, row) < 0)
+    move_vertical (clist, row, 0);
+  else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
+          clist->clist_window_height)
+    move_vertical (clist, row, 1);
+
+  return FALSE;
 }
 
 static void
-real_unselect_row (GtkCList * clist,
-                  gint row,
-                  gint column,
-                  GdkEvent * event)
+gtk_clist_size_request (GtkWidget      *widget,
+                       GtkRequisition *requisition)
 {
-  GtkCListRow *clist_row;
+  gint i;
+  GtkCList *clist;
 
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (requisition != NULL);
 
-  if (row < 0 || row > (clist->rows - 1))
-    return;
+  clist = GTK_CLIST (widget);
 
-  clist_row = (g_list_nth (clist->row_list, row))->data;
+  requisition->width = 0;
+  requisition->height = 0;
 
-  if (clist_row->state == GTK_STATE_SELECTED)
-    {
-      clist_row->state = GTK_STATE_NORMAL;
+  /* compute the size of the column title (title) area */
+  clist->column_title_area.height = 0;
+  if (GTK_CLIST_SHOW_TITLES (clist))
+    for (i = 0; i < clist->columns; i++)
+      if (clist->column[i].button)
+       {
+         gtk_widget_size_request (clist->column[i].button,
+                                  &clist->column[i].button->requisition);
+         clist->column_title_area.height =
+           MAX (clist->column_title_area.height,
+                clist->column[i].button->requisition.height);
+       }
+  requisition->height += clist->column_title_area.height;
 
-      if (clist->selection_end && 
-         clist->selection_end->data == GINT_TO_POINTER (row))
-       clist->selection_end = clist->selection_end->prev;
+  /* add the vscrollbar space */
+  if ((clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
+      GTK_WIDGET_VISIBLE (clist->vscrollbar))
+    {
+      gtk_widget_size_request (clist->vscrollbar,
+                              &clist->vscrollbar->requisition);
 
-      clist->selection = g_list_remove (clist->selection,
-                                       GINT_TO_POINTER (row));
-      
-      if (!GTK_CLIST_FROZEN (clist)
-         && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
+      requisition->width += (clist->vscrollbar->requisition.width +
+                            SCROLLBAR_SPACING (clist));
+      requisition->height = MAX (requisition->height,
+                                clist->vscrollbar->requisition.height);
     }
-}
-
-static gint
-get_selection_info (GtkCList * clist,
-                   gint x,
-                   gint y,
-                   gint * row,
-                   gint * column)
-{
-  gint trow, tcol;
-
-  g_return_val_if_fail (clist != NULL, 0);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
-
-  /* bounds checking, return false if the user clicked 
-   * on a blank area */
-  trow = ROW_FROM_YPIXEL (clist, y);
-  if (trow >= clist->rows)
-    return 0;
-
-  if (row)
-    *row = trow;
 
-  tcol = COLUMN_FROM_XPIXEL (clist, x);
-  if (tcol >= clist->columns)
-    return 0;
+  /* add the hscrollbar space */
+  if ((clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC) ||
+      GTK_WIDGET_VISIBLE (clist->hscrollbar))
+    {
+      gtk_widget_size_request (clist->hscrollbar,
+                              &clist->hscrollbar->requisition);
 
-  if (column)
-    *column = tcol;
+      requisition->height += (clist->hscrollbar->requisition.height +
+                             SCROLLBAR_SPACING (clist));
+      requisition->width = MAX (clist->hscrollbar->requisition.width, 
+                               requisition->width - 
+                               clist->vscrollbar->requisition.width);
 
-  return 1;
-}
+    }
 
-gint
-gtk_clist_get_selection_info (GtkCList *clist, 
-                             gint      x, 
-                             gint      y, 
-                             gint *    row, 
-                             gint *    column)
-{
-  g_return_val_if_fail (clist != NULL, 0);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
-  return get_selection_info (clist, x, y, row, column);
+  requisition->width += (widget->style->klass->xthickness +
+                        GTK_CONTAINER (widget)->border_width) * 2;
+  requisition->height += (widget->style->klass->ythickness +
+                         GTK_CONTAINER (widget)->border_width) * 2;
 }
 
-/* 
- * RESIZE COLUMNS
- *   draw_xor_line
- *   new_column_width
- *   resize_column
- */
-static void                          
-draw_xor_line (GtkCList * clist)
+static void
+gtk_clist_size_allocate (GtkWidget     *widget,
+                        GtkAllocation *allocation)
 {
-  GtkWidget *widget;
-
-  g_return_if_fail (clist != NULL);
-
-  widget = GTK_WIDGET (clist);
+  GtkCList *clist;
+  GtkAllocation clist_allocation;
+  GtkAllocation child_allocation;
+  gint i, vscrollbar_vis, hscrollbar_vis;
+  gint border_width;
 
-  gdk_draw_line (widget->window, clist->xor_gc,
-                 clist->x_drag,
-                widget->style->klass->ythickness,
-                 clist->x_drag,
-                 clist->column_title_area.height +
-                clist->clist_window_height + 1);
-}
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
+  g_return_if_fail (allocation != NULL);
 
-/* this function returns the new width of the column being resized given
- * the column and x position of the cursor; the x cursor position is passed
- * in as a pointer and automagicly corrected if it's beyond min/max limits */
-static gint
-new_column_width (GtkCList *clist,
-                 gint      column,
-                 gint     *x)
-{
-  gint xthickness = GTK_WIDGET (clist)->style->klass->xthickness;
-  gint width;
-  gint cx;
-  gint dx;
+  clist = GTK_CLIST (widget);
+  widget->allocation = *allocation;
+  border_width = GTK_CONTAINER (widget)->border_width;
 
-  /* first translate the x position from widget->window
-   * to clist->clist_window */
-  cx = *x - xthickness;
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (widget->window,
+                             allocation->x + border_width,
+                             allocation->y + border_width,
+                             allocation->width - border_width * 2,
+                             allocation->height - border_width * 2);
+    }
 
-  /* calculate new column width making sure it doesn't end up
-   * less than the minimum width */
-  dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
-       (column < clist->columns - 1) * CELL_SPACING);
-  width = cx - dx;
+  /* use internal allocation structure for all the math
+   * because it's easier than always subtracting the container
+   * border width */
+  clist->internal_allocation.x = 0;
+  clist->internal_allocation.y = 0;
+  clist->internal_allocation.width = MAX (1, allocation->width -
+                                         border_width * 2);
+  clist->internal_allocation.height = MAX (1, allocation->height -
+                                          border_width * 2);
+       
+  /* allocate clist window assuming no scrollbars */
+  clist_allocation.x = (clist->internal_allocation.x +
+                       widget->style->klass->xthickness);
+  clist_allocation.y = (clist->internal_allocation.y +
+                       widget->style->klass->ythickness +
+                       clist->column_title_area.height);
+  clist_allocation.width = MAX (1, clist->internal_allocation.width - 
+                               (2 * widget->style->klass->xthickness));
+  clist_allocation.height = MAX (1, clist->internal_allocation.height -
+                                (2 * widget->style->klass->ythickness) -
+                                clist->column_title_area.height);
+  
+  /* 
+   * here's where we decide to show/not show the scrollbars
+   */
+  vscrollbar_vis = 0;
+  hscrollbar_vis = 0;
+  
+  for (i = 0; i <= 1; i++)
+    {
+      if (LIST_HEIGHT (clist) <= clist_allocation.height &&
+         clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+       {
+         vscrollbar_vis = 0;
+       }
+      else if (!vscrollbar_vis)
+       {
+         vscrollbar_vis = 1;
+         clist_allocation.width = MAX (1, clist_allocation.width - 
+                                       (clist->vscrollbar->requisition.width +
+                                        SCROLLBAR_SPACING (clist)));
+       }  
+      
+      if (LIST_WIDTH (clist) <= clist_allocation.width &&
+         clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+       {
+         hscrollbar_vis = 0;
+       }
+      else if (!hscrollbar_vis)
+       {
+         hscrollbar_vis = 1;
+         clist_allocation.height = MAX (1, clist_allocation.height - 
+                                        (clist->hscrollbar->requisition.height
+                                         + SCROLLBAR_SPACING (clist)));
+       }  
+    }
+  
+  clist->clist_window_width = clist_allocation.width;
+  clist->clist_window_height = clist_allocation.height;
+  
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (clist->clist_window,
+                             clist_allocation.x,
+                             clist_allocation.y,
+                             clist_allocation.width,
+                             clist_allocation.height);
+    }
+  
+  /* position the window which holds the column title buttons */
+  clist->column_title_area.x = widget->style->klass->xthickness;
+  clist->column_title_area.y = widget->style->klass->ythickness;
+  clist->column_title_area.width = clist_allocation.width;
+  
+  if (GTK_WIDGET_REALIZED (widget))
+    {
+      gdk_window_move_resize (clist->title_window,
+                             clist->column_title_area.x,
+                             clist->column_title_area.y,
+                             clist->column_title_area.width,
+                             clist->column_title_area.height);
+    }
+  
+  /* column button allocation */
+  size_allocate_columns (clist);
+  size_allocate_title_buttons (clist);
 
-  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
+  adjust_scrollbars (clist);
+  
+  /* allocate the vscrollbar */
+  if (vscrollbar_vis)
     {
-      width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
-      cx = dx + width;
-      *x = cx + xthickness;
+      if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
+       gtk_widget_show (clist->vscrollbar);
+      
+      child_allocation.x = (clist->internal_allocation.x + 
+                           clist->internal_allocation.width -
+                           clist->vscrollbar->requisition.width);
+      child_allocation.y = clist->internal_allocation.y;
+      child_allocation.width = clist->vscrollbar->requisition.width;
+      child_allocation.height = MAX (1, clist->internal_allocation.height -
+                                    (hscrollbar_vis ?
+                                     (clist->hscrollbar->requisition.height +
+                                      SCROLLBAR_SPACING (clist)) : 0));
+      gtk_widget_size_allocate (clist->vscrollbar, &child_allocation);
     }
-  else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
-          width > clist->column[column].max_width)
+  else
     {
-      width = clist->column[column].max_width;
-      cx = dx + clist->column[column].max_width;
-      *x = cx + xthickness;
-    }      
-
-  if (cx < 0 || cx > clist->clist_window_width)
-    *x = -1;
-
-  return width;
-}
-
-/* this will do more later */
-static void
-resize_column (GtkCList * clist,
-              gint column,
-              gint width)
-{
-  gtk_clist_set_column_width (clist, column, width);
-}
-
-/* BUTTONS */
-static void
-column_button_create (GtkCList * clist,
-                     gint column)
-{
-  GtkWidget *button;
-
-  button = clist->column[column].button = gtk_button_new ();
-  if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
-    gtk_widget_set_parent_window (clist->column[column].button, clist->title_window);
-  gtk_widget_set_parent (button, GTK_WIDGET (clist));
+      if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
+       gtk_widget_hide (clist->vscrollbar);
+    }
   
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-                     (GtkSignalFunc) column_button_clicked,
-                     (gpointer) clist);
+  if (hscrollbar_vis)
+    {
+      if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
+       gtk_widget_show (clist->hscrollbar);
+      
+      child_allocation.x = clist->internal_allocation.x;
+      child_allocation.y = (clist->internal_allocation.y +
+                           clist->internal_allocation.height -
+                           clist->hscrollbar->requisition.height);
+      child_allocation.width = MAX (1, clist->internal_allocation.width -
+                                   (vscrollbar_vis ?
+                                    (clist->vscrollbar->requisition.width +
+                                     SCROLLBAR_SPACING (clist)) : 0));
+      child_allocation.height = clist->hscrollbar->requisition.height;
+      
+      gtk_widget_size_allocate (clist->hscrollbar, &child_allocation);
+    }
+  else
+    {
+      if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
+       gtk_widget_hide (clist->hscrollbar);
+    }
 
-  gtk_widget_show (button);
+  /* set the vscrollbar adjustments */
+  adjust_scrollbars (clist);
 }
 
+/* GTKCONTAINER
+ *   gtk_clist_forall
+ */
 static void
-column_button_clicked (GtkWidget * widget,
-                      gpointer data)
+gtk_clist_forall (GtkContainer *container,
+                 gboolean      include_internals,
+                 GtkCallback   callback,
+                 gpointer      callback_data)
 {
-  gint i;
   GtkCList *clist;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (data));
-
-  clist = GTK_CLIST (data);
-
-  /* find the column who's button was pressed */
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].button == widget)
-      break;
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (GTK_IS_CLIST (container));
+  g_return_if_fail (callback != NULL);
 
-  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
+  clist = GTK_CLIST (container);
+      
+  if (include_internals)
+    {
+      guint i;
+      
+      /* callback for the column buttons */
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].button)
+         (*callback) (clist->column[i].button, callback_data);
+      
+      /* callbacks for the scrollbars */
+      if (clist->vscrollbar)
+       (*callback) (clist->vscrollbar, callback_data);
+      if (clist->hscrollbar)
+       (*callback) (clist->hscrollbar, callback_data);
+    }
 }
 
-/* 
- * SCROLLBARS
- *
- * functions:
- *   create_scrollbars
- *   adjust_scrollbars
- *   vadjustment_changed
- *   hadjustment_changed
- *   vadjustment_value_changed
- *   hadjustment_value_changed 
+/* PRIVATE DRAWING FUNCTIONS
+ *   get_cell_style
+ *   draw_cell_pixmap
+ *   draw_row
+ *   draw_rows
+ *   draw_xor_line
  */
 static void
-create_scrollbars (GtkCList * clist)
-{
-  GtkAdjustment *adjustment;
-
-  clist->vscrollbar = gtk_vscrollbar_new (NULL);
-
-  adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
-
-  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
-                     (GtkSignalFunc) vadjustment_changed,
-                     (gpointer) clist);
-
-  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
-                     (GtkSignalFunc) vadjustment_value_changed,
-                     (gpointer) clist);
-
-  gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
-  gtk_widget_show (clist->vscrollbar);
-
-  clist->hscrollbar = gtk_hscrollbar_new (NULL);
-
-  adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
-
-  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
-                     (GtkSignalFunc) hadjustment_changed,
-                     (gpointer) clist);
-
-  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
-                     (GtkSignalFunc) hadjustment_value_changed,
-                     (gpointer) clist);
-
-  gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
-  gtk_widget_show (clist->hscrollbar);
-}
-
-static void
-adjust_scrollbars (GtkCList * clist)
+get_cell_style (GtkCList     *clist,
+               GtkCListRow  *clist_row,
+               gint          state,
+               gint          column,
+               GtkStyle    **style,
+               GdkGC       **fg_gc,
+               GdkGC       **bg_gc)
 {
-  GTK_RANGE (clist->vscrollbar)->adjustment->page_size = clist->clist_window_height;
-  GTK_RANGE (clist->vscrollbar)->adjustment->page_increment = clist->clist_window_height / 2;
-  GTK_RANGE (clist->vscrollbar)->adjustment->step_increment = 10;
-  GTK_RANGE (clist->vscrollbar)->adjustment->lower = 0;
-  GTK_RANGE (clist->vscrollbar)->adjustment->upper = LIST_HEIGHT (clist);
-
-  if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
+  if (clist_row->cell[column].style)
     {
-      GTK_RANGE (clist->vscrollbar)->adjustment->value = MAX (0, LIST_HEIGHT (clist) - 
-       clist->clist_window_height);
-      gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), 
-                              "value_changed");
+      if (style)
+       *style = clist_row->cell[column].style;
+      if (fg_gc)
+       *fg_gc = clist_row->cell[column].style->fg_gc[state];
+      if (bg_gc)
+       *bg_gc = clist_row->cell[column].style->bg_gc[state];
     }
-
-  GTK_RANGE (clist->hscrollbar)->adjustment->page_size = clist->clist_window_width;
-  GTK_RANGE (clist->hscrollbar)->adjustment->page_increment = clist->clist_window_width / 2;
-  GTK_RANGE (clist->hscrollbar)->adjustment->step_increment = 10;
-  GTK_RANGE (clist->hscrollbar)->adjustment->lower = 0;
-  GTK_RANGE (clist->hscrollbar)->adjustment->upper = LIST_WIDTH (clist);
-
-  if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
+  else if (clist_row->style)
     {
-      GTK_RANGE (clist->hscrollbar)->adjustment->value = MAX (0, LIST_WIDTH (clist) - 
-       clist->clist_window_width);
-      gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), 
-                              "value_changed");
+      if (style)
+       *style = clist_row->style;
+      if (fg_gc)
+       *fg_gc = clist_row->style->fg_gc[state];
+      if (bg_gc)
+       *bg_gc = clist_row->style->bg_gc[state];
     }
-
-  if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
-      clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+  else
     {
-      if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
+      if (style)
+       *style = GTK_WIDGET (clist)->style;
+      if (fg_gc)
+       *fg_gc = GTK_WIDGET (clist)->style->fg_gc[state];
+      if (bg_gc)
+       *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
+
+      if (state != GTK_STATE_SELECTED)
        {
-         gtk_widget_hide (clist->vscrollbar);
-         gtk_widget_size_allocate (GTK_WIDGET (clist),
-                                   &GTK_WIDGET (clist)->allocation);
+         if (fg_gc && clist_row->fg_set)
+           *fg_gc = clist->fg_gc;
+         if (bg_gc && clist_row->bg_set)
+           *bg_gc = clist->bg_gc;
        }
     }
-  else
+}
+
+static gint
+draw_cell_pixmap (GdkWindow    *window,
+                 GdkRectangle *clip_rectangle,
+                 GdkGC        *fg_gc,
+                 GdkPixmap    *pixmap,
+                 GdkBitmap    *mask,
+                 gint          x,
+                 gint          y,
+                 gint          width,
+                 gint          height)
+{
+  gint xsrc = 0;
+  gint ysrc = 0;
+
+  if (mask)
     {
-      if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
-       {
-         gtk_widget_show (clist->vscrollbar);
-         gtk_widget_size_allocate (GTK_WIDGET (clist),
-                                   &GTK_WIDGET (clist)->allocation);
-       }
+      gdk_gc_set_clip_mask (fg_gc, mask);
+      gdk_gc_set_clip_origin (fg_gc, x, y);
     }
 
-  if (LIST_WIDTH (clist) <= clist->clist_window_width &&
-      clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
+  if (x < clip_rectangle->x)
     {
-      if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
-       {
-         gtk_widget_hide (clist->hscrollbar);
-         gtk_widget_size_allocate (GTK_WIDGET (clist),
-                                   &GTK_WIDGET (clist)->allocation);
-       }
+      xsrc = clip_rectangle->x - x;
+      width -= xsrc;
+      x = clip_rectangle->x;
     }
-  else
+  if (x + width > clip_rectangle->x + clip_rectangle->width)
+    width = clip_rectangle->x + clip_rectangle->width - x;
+
+  if (y < clip_rectangle->y)
     {
-      if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
-       {
-         gtk_widget_show (clist->hscrollbar);
-         gtk_widget_size_allocate (GTK_WIDGET (clist),
-                                   &GTK_WIDGET (clist)->allocation);
-       }
+      ysrc = clip_rectangle->y - y;
+      height -= ysrc;
+      y = clip_rectangle->y;
     }
+  if (y + height > clip_rectangle->y + clip_rectangle->height)
+    height = clip_rectangle->y + clip_rectangle->height - y;
 
-  gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->vscrollbar)->adjustment), "changed");
-  gtk_signal_emit_by_name (GTK_OBJECT (GTK_RANGE (clist->hscrollbar)->adjustment), "changed");
+  gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
+  gdk_gc_set_clip_origin (fg_gc, 0, 0);
+
+  return x + MAX (width, 0);
 }
 
 static void
-vadjustment_changed (GtkAdjustment * adjustment,
-                              gpointer data)
+draw_row (GtkCList     *clist,
+         GdkRectangle *area,
+         gint          row,
+         GtkCListRow  *clist_row)
 {
-  GtkCList *clist;
+  GtkWidget *widget;
+  GdkRectangle *rect;
+  GdkRectangle row_rectangle;
+  GdkRectangle cell_rectangle;
+  GdkRectangle clip_rectangle;
+  GdkRectangle intersect_rectangle;
+  gint state;
+  gint i;
 
-  g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
+  g_return_if_fail (clist != NULL);
 
-  clist = GTK_CLIST (data);
-}
+  /* bail now if we arn't drawable yet */
+  if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
+    return;
 
-static void
-hadjustment_changed (GtkAdjustment * adjustment,
-                              gpointer data)
-{
-  GtkCList *clist;
+  widget = GTK_WIDGET (clist);
 
-  g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
+  /* if the function is passed the pointer to the row instead of null,
+   * it avoids this expensive lookup */
+  if (!clist_row)
+    clist_row = (g_list_nth (clist->row_list, row))->data;
 
-  clist = GTK_CLIST (data);
-}
+  /* rectangle of the entire row */
+  row_rectangle.x = 0;
+  row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
+  row_rectangle.width = clist->clist_window_width;
+  row_rectangle.height = clist->row_height;
 
-static void
-check_exposures (GtkCList *clist)
-{
-  GdkEvent *event;
+  /* rectangle of the cell spacing above the row */
+  cell_rectangle.x = 0;
+  cell_rectangle.y = row_rectangle.y - CELL_SPACING;
+  cell_rectangle.width = row_rectangle.width;
+  cell_rectangle.height = CELL_SPACING;
 
-  if (!GTK_WIDGET_REALIZED (clist))
-    return;
+  /* rectangle used to clip drawing operations, it's y and height
+   * positions only need to be set once, so we set them once here. 
+   * the x and width are set withing the drawing loop below once per
+   * column */
+  clip_rectangle.y = row_rectangle.y;
+  clip_rectangle.height = row_rectangle.height;
 
-  /* Make sure graphics expose events are processed before scrolling
-   * again */
-  while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
+  if (clist_row->state == GTK_STATE_NORMAL)
     {
-      gtk_widget_event (GTK_WIDGET (clist), event);
-      if (event->expose.count == 0)
+      state = GTK_STATE_PRELIGHT;
+      if (clist_row->fg_set)
+       gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
+      if (clist_row->bg_set)
+       gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
+    }
+  else
+    state = clist_row->state;
+
+  /* draw the cell borders and background */
+  if (area)
+    {
+      rect = &intersect_rectangle;
+      if (gdk_rectangle_intersect (area, &cell_rectangle,
+                                  &intersect_rectangle))
+       gdk_draw_rectangle (clist->clist_window,
+                           widget->style->base_gc[GTK_STATE_NORMAL],
+                           TRUE,
+                           intersect_rectangle.x,
+                           intersect_rectangle.y,
+                           intersect_rectangle.width,
+                           intersect_rectangle.height);
+
+      /* the last row has to clear it's bottom cell spacing too */
+      if (clist_row == clist->row_list_end->data)
        {
-         gdk_event_free (event);
-         break;
+         cell_rectangle.y += clist->row_height + CELL_SPACING;
+
+         if (gdk_rectangle_intersect (area, &cell_rectangle,
+                                      &intersect_rectangle))
+           gdk_draw_rectangle (clist->clist_window,
+                               widget->style->base_gc[GTK_STATE_NORMAL],
+                               TRUE,
+                               intersect_rectangle.x,
+                               intersect_rectangle.y,
+                               intersect_rectangle.width,
+                               intersect_rectangle.height);
        }
-      gdk_event_free (event);
+
+      if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
+       return;
+
     }
-}
+  else
+    {
+      rect = &clip_rectangle;
+      gdk_draw_rectangle (clist->clist_window,
+                         widget->style->base_gc[GTK_STATE_NORMAL],
+                         TRUE,
+                         cell_rectangle.x,
+                         cell_rectangle.y,
+                         cell_rectangle.width,
+                         cell_rectangle.height);
 
-static void
-vadjustment_value_changed (GtkAdjustment * adjustment,
-                                    gpointer data)
-{
-  GtkCList *clist;
-  GdkRectangle area;
-  gint diff, value;
+      /* the last row has to clear it's bottom cell spacing too */
+      if (clist_row == clist->row_list_end->data)
+       {
+         cell_rectangle.y += clist->row_height + CELL_SPACING;
 
-  g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (GTK_IS_CLIST (data));
+         gdk_draw_rectangle (clist->clist_window,
+                             widget->style->base_gc[GTK_STATE_NORMAL],
+                             TRUE,
+                             cell_rectangle.x,
+                             cell_rectangle.y,
+                             cell_rectangle.width,
+                             cell_rectangle.height);     
+       }         
+    }
+  
+  /* iterate and draw all the columns (row cells) and draw their contents */
+  for (i = 0; i < clist->columns; i++)
+    {
+      GtkStyle *style;
+      GdkGC *fg_gc;
+      GdkGC *bg_gc;
 
-  clist = GTK_CLIST (data);
+      gint width;
+      gint height;
+      gint pixmap_width;
+      gint offset = 0;
+      gint row_center_offset;
 
-  if (!GTK_WIDGET_DRAWABLE (clist))
-    return;
+      if (!clist->column[i].visible)
+       continue;
 
-  value = adjustment->value;
+      get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
 
-  if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
-    {
-      if (value > -clist->voffset)
-       {
-         /* scroll down */
-         diff = value + clist->voffset;
+      clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
+      clip_rectangle.width = clist->column[i].area.width;
 
-         /* we have to re-draw the whole screen here... */
-         if (diff >= clist->clist_window_height)
-           {
-             clist->voffset = -value;
-             draw_rows (clist, NULL);
-             return;
-           }
+      /* calculate clipping region clipping region */
+      clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
+      clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
+                              (i + 1 == clist->columns) * CELL_SPACING);
+      
+      if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
+                                           &intersect_rectangle))
+       continue;
 
-         if ((diff != 0) && (diff != clist->clist_window_height))
-           gdk_window_copy_area (clist->clist_window,
-                                 clist->fg_gc,
-                                 0, 0,
-                                 clist->clist_window,
-                                 0,
-                                 diff,
-                                 clist->clist_window_width,
-                                 clist->clist_window_height - diff);
+      gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
+                         rect->x, rect->y, rect->width, rect->height);
 
-         area.x = 0;
-         area.y = clist->clist_window_height - diff;
-         area.width = clist->clist_window_width;
-         area.height = diff;
-       }
-      else
-       {
-         /* scroll up */
-         diff = -clist->voffset - value;
+      clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
+      clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
+                              (i + 1 == clist->columns) * CELL_SPACING);
 
-         /* we have to re-draw the whole screen here... */
-         if (diff >= clist->clist_window_height)
-           {
-             clist->voffset = -value;
-             draw_rows (clist, NULL);
-             return;
-           }
+      /* calculate real width for column justification */
+      pixmap_width = 0;
+      offset = 0;
+      switch (clist_row->cell[i].type)
+       {
+       case GTK_CELL_TEXT:
+         width = gdk_string_width (style->font,
+                                   GTK_CELL_TEXT (clist_row->cell[i])->text);
+         break;
+       case GTK_CELL_PIXMAP:
+         gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
+                              &pixmap_width, &height);
+         width = pixmap_width;
+         break;
+       case GTK_CELL_PIXTEXT:
+         gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                              &pixmap_width, &height);
+         width = (pixmap_width +
+                  GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing +
+                  gdk_string_width (style->font,
+                                    GTK_CELL_PIXTEXT
+                                    (clist_row->cell[i])->text));
+         break;
+       default:
+         continue;
+         break;
+       }
 
-         if ((diff != 0) && (diff != clist->clist_window_height))
-           gdk_window_copy_area (clist->clist_window,
-                                 clist->fg_gc,
-                                 0, diff,
-                                 clist->clist_window,
-                                 0,
-                                 0,
-                                 clist->clist_window_width,
-                                 clist->clist_window_height - diff);
+      switch (clist->column[i].justification)
+       {
+       case GTK_JUSTIFY_LEFT:
+         offset = clip_rectangle.x + clist_row->cell[i].horizontal;
+         break;
+       case GTK_JUSTIFY_RIGHT:
+         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                   clip_rectangle.width - width);
+         break;
+       case GTK_JUSTIFY_CENTER:
+       case GTK_JUSTIFY_FILL:
+         offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
+                   (clip_rectangle.width / 2) - (width / 2));
+         break;
+       };
 
-         area.x = 0;
-         area.y = 0;
-         area.width = clist->clist_window_width;
-         area.height = diff;
+      /* Draw Text and/or Pixmap */
+      switch (clist_row->cell[i].type)
+       {
+       case GTK_CELL_PIXMAP:
+         draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+                           GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
+                           GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
+                           offset,
+                           clip_rectangle.y + clist_row->cell[i].vertical +
+                           (clip_rectangle.height - height) / 2,
+                           pixmap_width, height);
+         break;
+       case GTK_CELL_PIXTEXT:
+         offset =
+           draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
+                             GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
+                             GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
+                             offset,
+                             clip_rectangle.y + clist_row->cell[i].vertical+
+                             (clip_rectangle.height - height) / 2,
+                             pixmap_width, height);
+         offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
+       case GTK_CELL_TEXT:
+         if (style != GTK_WIDGET (clist)->style)
+           row_center_offset = (((clist->row_height - style->font->ascent -
+                                 style->font->descent - 1) / 2) + 1.5 +
+                                style->font->ascent);
+         else
+           row_center_offset = clist->row_center_offset;
 
+         gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
+         gdk_draw_string (clist->clist_window, style->font, fg_gc,
+                          offset,
+                          row_rectangle.y + row_center_offset + 
+                          clist_row->cell[i].vertical,
+                          (clist_row->cell[i].type == GTK_CELL_PIXTEXT) ?
+                          GTK_CELL_PIXTEXT (clist_row->cell[i])->text :
+                          GTK_CELL_TEXT (clist_row->cell[i])->text);
+         gdk_gc_set_clip_rectangle (fg_gc, NULL);
+         break;
+       default:
+         break;
        }
-
-      clist->voffset = -value;
-      if ((diff != 0) && (diff != clist->clist_window_height))
-       check_exposures (clist);
     }
 
-  draw_rows (clist, &area);
+  /* draw focus rectangle */
+  if (clist->focus_row == row && GTK_WIDGET_HAS_FOCUS (widget))
+    {
+      if (!area)
+       gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                           row_rectangle.x, row_rectangle.y,
+                           row_rectangle.width - 1, row_rectangle.height - 1);
+      else if (gdk_rectangle_intersect (area, &row_rectangle,
+                                       &intersect_rectangle))
+       {
+         gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                             row_rectangle.x, row_rectangle.y,
+                             row_rectangle.width - 1,
+                             row_rectangle.height - 1);
+         gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
+       }
+    }
 }
 
 static void
-hadjustment_value_changed (GtkAdjustment * adjustment,
-                                    gpointer data)
+draw_rows (GtkCList     *clist,
+          GdkRectangle *area)
 {
-  GtkCList *clist;
-  GdkRectangle area;
+  GList *list;
+  GtkCListRow *clist_row;
   gint i;
-  gint y = 0;
-  gint diff = 0;
-  gint value;
-
-  g_return_if_fail (adjustment != NULL);
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (GTK_IS_CLIST (data));
+  gint first_row;
+  gint last_row;
 
-  clist = GTK_CLIST (data);
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_WIDGET_DRAWABLE (clist) ||
-      adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
+  if (clist->row_height == 0 ||
+      !GTK_WIDGET_DRAWABLE (clist))
     return;
 
-  value = adjustment->value;
-  
-  /* move the column buttons and resize windows */
-  for (i = 0; i < clist->columns; i++)
-    {
-      if (clist->column[i].button)
-       {
-         clist->column[i].button->allocation.x -= value + clist->hoffset;
-         
-         if (clist->column[i].button->window)
-           {
-             gdk_window_move (clist->column[i].button->window,
-                              clist->column[i].button->allocation.x,
-                              clist->column[i].button->allocation.y);
-             
-             if (clist->column[i].window)
-               gdk_window_move (clist->column[i].window,
-                                clist->column[i].button->allocation.x +
-                                clist->column[i].button->allocation.width - 
-                                (DRAG_WIDTH / 2), 0); 
-           }
-       }
-    }
-
-  if (value > -clist->hoffset)
+  if (area)
     {
-      /* scroll right */
-      diff = value + clist->hoffset;
-      
-      clist->hoffset = -value;
-      
-      /* we have to re-draw the whole screen here... */
-      if (diff >= clist->clist_window_width)
-       {
-         draw_rows (clist, NULL);
-         return;
-       }
-
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
-       {
-         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
-             
-         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
-                             clist->clist_window_width - 1,
-                             clist->row_height - 1);
-       }
-      gdk_window_copy_area (clist->clist_window,
-                           clist->fg_gc,
-                           0, 0,
-                           clist->clist_window,
-                           diff,
-                           0,
-                           clist->clist_window_width - diff,
-                           clist->clist_window_height);
-
-      area.x = clist->clist_window_width - diff;
+      first_row = ROW_FROM_YPIXEL (clist, area->y);
+      last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
     }
   else
     {
-      /* scroll left */
-      if (!(diff = -clist->hoffset - value))
-       return;
-
-      clist->hoffset = -value;
-      
-      /* we have to re-draw the whole screen here... */
-      if (diff >= clist->clist_window_width)
-       {
-         draw_rows (clist, NULL);
-         return;
-       }
-      
-      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_CLIST_ADD_MODE (clist))
-       {
-         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
-         
-         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
-                             clist->clist_window_width - 1,
-                             clist->row_height - 1);
-       }
-
-      gdk_window_copy_area (clist->clist_window,
-                           clist->fg_gc,
-                           diff, 0,
-                           clist->clist_window,
-                           0,
-                           0,
-                           clist->clist_window_width - diff,
-                           clist->clist_window_height);
-         
-      area.x = 0;
+      first_row = ROW_FROM_YPIXEL (clist, 0);
+      last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
     }
 
-  area.y = 0;
-  area.width = diff;
-  area.height = clist->clist_window_height;
-
-  check_exposures (clist);
+  /* this is a small special case which exposes the bottom cell line
+   * on the last row -- it might go away if I change the wall the cell
+   * spacings are drawn
+   */
+  if (clist->rows == first_row)
+    first_row--;
 
-  if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+  list = g_list_nth (clist->row_list, first_row);
+  i = first_row;
+  while (list)
     {
-      if (GTK_CLIST_ADD_MODE (clist))
-       {
-         gint focus_row;
-         
-         focus_row = clist->focus_row;
-         clist->focus_row = -1;
-         draw_rows (clist, &area);
-         clist->focus_row = focus_row;
-         
-         gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
-                             FALSE, 0, y, clist->clist_window_width - 1,
-                             clist->row_height - 1);
-         return;
-       }
-      else
-       {
-         gint x0;
-         gint x1;
-         
-         if (area.x == 0)
-           {
-             x0 = clist->clist_window_width - 1;
-             x1 = diff;
-           }
-         else
-           {
-             x0 = 0;
-             x1 = area.x - 1;
-           }
-         
-         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
-         gdk_draw_line (clist->clist_window, clist->xor_gc,
-                        x0, y + 1, x0, y + clist->row_height - 2);
-         gdk_draw_line (clist->clist_window, clist->xor_gc,
-                        x1, y + 1, x1, y + clist->row_height - 2);
-         
-       }
-    }
-  draw_rows (clist, &area);
-}
-
-/* 
- * Memory Allocation/Distruction Routines for GtkCList stuctures
- *
- * functions:
- *   columns_new
- *   column_title_new
- *   columns_delete
- *   row_new
- *   row_delete
- *   set_cell_contents 
- */
-static GtkCListColumn *
-columns_new (GtkCList * clist)
-{
-  gint i;
-  GtkCListColumn *column;
+      clist_row = list->data;
+      list = list->next;
 
-  column = g_new (GtkCListColumn, clist->columns);
+      if (i > last_row)
+       return;
 
-  for (i = 0; i < clist->columns; i++)
-    {
-      column[i].area.x = 0;
-      column[i].area.y = 0;
-      column[i].area.width = 0;
-      column[i].area.height = 0;
-      column[i].title = NULL;
-      column[i].button = NULL;
-      column[i].window = NULL;
-      column[i].width = 0;
-      column[i].min_width = -1;
-      column[i].max_width = -1;
-      column[i].visible = TRUE;
-      column[i].width_set = FALSE;
-      column[i].resizeable = TRUE;
-      column[i].justification = GTK_JUSTIFY_LEFT;
+      GTK_CLIST_CLASS_FW (clist)->draw_row (clist, area, i, clist_row);
+      i++;
     }
 
-  return column;
+  if (!area)
+    gdk_window_clear_area (clist->clist_window,
+                          0, ROW_TOP_YPIXEL (clist, i), -1, -1);
 }
 
-static void
-column_title_new (GtkCList    *clist,
-                 gint         column,
-                 const gchar *title)
+static void                          
+draw_xor_line (GtkCList *clist)
 {
-  if (clist->column[column].title)
-    g_free (clist->column[column].title);
+  GtkWidget *widget;
 
-  clist->column[column].title = g_strdup (title);
-}
+  g_return_if_fail (clist != NULL);
 
-static void
-columns_delete (GtkCList * clist)
-{
-  gint i;
+  widget = GTK_WIDGET (clist);
 
-  for (i = 0; i < clist->columns; i++)
-    if (clist->column[i].title)
-      g_free (clist->column[i].title);
-      
-  g_free (clist->column);
+  gdk_draw_line (widget->window, clist->xor_gc,
+                 clist->x_drag,
+                widget->style->klass->ythickness,
+                 clist->x_drag,
+                 clist->column_title_area.height +
+                clist->clist_window_height + 1);
 }
 
-static GtkCListRow *
-row_new (GtkCList * clist)
+/* get cell from coordinates
+ *   get_selection_info
+ *   gtk_clist_get_selection_info
+ */
+static gint
+get_selection_info (GtkCList *clist,
+                   gint      x,
+                   gint      y,
+                   gint     *row,
+                   gint     *column)
 {
-  int i;
-  GtkCListRow *clist_row;
+  gint trow, tcol;
 
-  clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
-  clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
-  for (i = 0; i < clist->columns; i++)
-    {
-      clist_row->cell[i].type = GTK_CELL_EMPTY;
-      clist_row->cell[i].vertical = 0;
-      clist_row->cell[i].horizontal = 0;
-      clist_row->cell[i].style = NULL;
-    }
+  /* bounds checking, return false if the user clicked 
+   * on a blank area */
+  trow = ROW_FROM_YPIXEL (clist, y);
+  if (trow >= clist->rows)
+    return 0;
 
-  clist_row->fg_set = FALSE;
-  clist_row->bg_set = FALSE;
-  clist_row->style = NULL;
-  clist_row->selectable = TRUE;
-  clist_row->state = GTK_STATE_NORMAL;
-  clist_row->data = NULL;
-  clist_row->destroy = NULL;
+  if (row)
+    *row = trow;
 
-  return clist_row;
+  tcol = COLUMN_FROM_XPIXEL (clist, x);
+  if (tcol >= clist->columns)
+    return 0;
+
+  if (column)
+    *column = tcol;
+
+  return 1;
+}
+
+gint
+gtk_clist_get_selection_info (GtkCList *clist, 
+                             gint      x, 
+                             gint      y, 
+                             gint     *row, 
+                             gint     *column)
+{
+  g_return_val_if_fail (clist != NULL, 0);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
+  return get_selection_info (clist, x, y, row, column);
 }
 
+/* 
+ * SCROLLBARS
+ *
+ * functions:
+ *   create_scrollbars
+ *   adjust_scrollbars
+ *   vadjustment_changed
+ *   hadjustment_changed
+ *   vadjustment_value_changed
+ *   hadjustment_value_changed 
+ *   check_exposures
+ */
 static void
-row_delete (GtkCList * clist,
-           GtkCListRow * clist_row)
+create_scrollbars (GtkCList *clist)
 {
-  gint i;
+  GtkAdjustment *adjustment;
 
-  for (i = 0; i < clist->columns; i++)
-    {
-      GTK_CLIST_CLASS_FW (clist)->set_cell_contents
-       (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
-      if (clist_row->cell[i].style)
-       {
-         if (GTK_WIDGET_REALIZED (clist))
-           gtk_style_detach (clist_row->cell[i].style);
-         gtk_style_unref (clist_row->cell[i].style);
-       }
-    }
+  clist->vscrollbar = gtk_vscrollbar_new (NULL);
 
-  if (clist_row->style)
-    {
-      if (GTK_WIDGET_REALIZED (clist))
-        gtk_style_detach (clist_row->style);
-      gtk_style_unref (clist_row->style);
-    }
+  adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar));
 
-  if (clist_row->destroy)
-    clist_row->destroy (clist_row->data);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+                     (GtkSignalFunc) vadjustment_changed,
+                     (gpointer) clist);
 
-  g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
-  g_mem_chunk_free (clist->row_mem_chunk, clist_row);
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+                     (GtkSignalFunc) vadjustment_value_changed,
+                     (gpointer) clist);
+
+  gtk_widget_set_parent (clist->vscrollbar, GTK_WIDGET (clist));
+  gtk_widget_show (clist->vscrollbar);
+
+  clist->hscrollbar = gtk_hscrollbar_new (NULL);
+
+  adjustment = gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar));
+
+  gtk_signal_connect (GTK_OBJECT (adjustment), "changed",
+                     (GtkSignalFunc) hadjustment_changed,
+                     (gpointer) clist);
+
+  gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
+                     (GtkSignalFunc) hadjustment_value_changed,
+                     (gpointer) clist);
+
+  gtk_widget_set_parent (clist->hscrollbar, GTK_WIDGET (clist));
+  gtk_widget_show (clist->hscrollbar);
 }
 
 static void
-set_cell_contents (GtkCList    *clist,
-                  GtkCListRow *clist_row,
-                  gint         column,
-                  GtkCellType  type,
-                  const gchar *text,
-                  guint8       spacing,
-                  GdkPixmap   *pixmap,
-                  GdkBitmap   *mask)
+adjust_scrollbars (GtkCList * clist)
 {
-  g_return_if_fail (clist_row != NULL);
+  GtkRange *vscrollbar;
+  GtkRange *hscrollbar;
 
-  switch (clist_row->cell[column].type)
+  vscrollbar = GTK_RANGE (clist->vscrollbar);
+  vscrollbar->adjustment->page_size = clist->clist_window_height;
+  vscrollbar->adjustment->page_increment = clist->clist_window_height / 2;
+  vscrollbar->adjustment->step_increment = 10;
+  vscrollbar->adjustment->lower = 0;
+  vscrollbar->adjustment->upper = LIST_HEIGHT (clist);
+
+  if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist))
     {
-    case GTK_CELL_EMPTY:
-      break;
-    case GTK_CELL_TEXT:
-      g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
-      break;
-    case GTK_CELL_PIXMAP:
-      gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
-      if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
-       gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
-      break;
-    case GTK_CELL_PIXTEXT:
-      g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
-      gdk_pixmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap);
-      if (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask)
-       gdk_bitmap_unref (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
-      break;
-    case GTK_CELL_WIDGET:
-      /* unimplimented */
-      break;
-    default:
-      break;
+      vscrollbar->adjustment->value = MAX (0, LIST_HEIGHT (clist) - 
+                                          clist->clist_window_height);
+      gtk_signal_emit_by_name (GTK_OBJECT (vscrollbar->adjustment), 
+                              "value_changed");
     }
 
-  clist_row->cell[column].type = GTK_CELL_EMPTY;
+  hscrollbar = GTK_RANGE (clist->hscrollbar);
+  hscrollbar->adjustment->page_size = clist->clist_window_width;
+  hscrollbar->adjustment->page_increment = clist->clist_window_width / 2;
+  hscrollbar->adjustment->step_increment = 10;
+  hscrollbar->adjustment->lower = 0;
+  hscrollbar->adjustment->upper = LIST_WIDTH (clist);
 
-  switch (type)
+  if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist))
     {
-    case GTK_CELL_TEXT:
-      if (text)
-       {
-         clist_row->cell[column].type = GTK_CELL_TEXT;
-         GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
-       }
-      break;
-    case GTK_CELL_PIXMAP:
-      if (pixmap)
+      hscrollbar->adjustment->value = MAX (0, LIST_WIDTH (clist) - 
+                                          clist->clist_window_width);
+      gtk_signal_emit_by_name (GTK_OBJECT (hscrollbar->adjustment), 
+                              "value_changed");
+    }
+
+  if (LIST_HEIGHT (clist) <= clist->clist_window_height &&
+      clist->vscrollbar_policy == GTK_POLICY_AUTOMATIC)
+    {
+      if (GTK_WIDGET_VISIBLE (clist->vscrollbar))
        {
-         clist_row->cell[column].type = GTK_CELL_PIXMAP;
-         GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
-         /* We set the mask even if it is NULL */
-         GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
+         gtk_widget_hide (clist->vscrollbar);
+         gtk_widget_size_allocate (GTK_WIDGET (clist),
+                                   &GTK_WIDGET (clist)->allocation);
        }
-      break;
-    case GTK_CELL_PIXTEXT:
-      if (text && pixmap)
+    }
+  else
+    {
+      if (!GTK_WIDGET_VISIBLE (clist->vscrollbar))
        {
-         clist_row->cell[column].type = GTK_CELL_PIXTEXT;
-         GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
-         GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
-         GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
-         GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
+         gtk_widget_show (clist->vscrollbar);
+         gtk_widget_size_allocate (GTK_WIDGET (clist),
+                                   &GTK_WIDGET (clist)->allocation);
        }
-      break;
-    default:
-      break;
     }
-}
-
-/* Fill in data after widget has correct style */
-
-static void 
-add_style_data (GtkCList * clist)
-{
-  GtkWidget *widget;
-
-  widget = GTK_WIDGET(clist);
 
-  /* text properties */
-  if (!GTK_CLIST_ROW_HEIGHT_SET (clist))
+  if (LIST_WIDTH (clist) <= clist->clist_window_width &&
+      clist->hscrollbar_policy == GTK_POLICY_AUTOMATIC)
     {
-      clist->row_height = widget->style->font->ascent + widget->style->font->descent + 1;
-      clist->row_center_offset = widget->style->font->ascent + 1.5;
+      if (GTK_WIDGET_VISIBLE (clist->hscrollbar))
+       {
+         gtk_widget_hide (clist->hscrollbar);
+         gtk_widget_size_allocate (GTK_WIDGET (clist),
+                                   &GTK_WIDGET (clist)->allocation);
+       }
     }
   else
     {
-      gint text_height;
-      text_height = clist->row_height - (GTK_WIDGET (clist)->style->font->ascent +
-                         GTK_WIDGET (clist) ->style->font->descent + 1);
-      clist->row_center_offset = (text_height / 2) + GTK_WIDGET (clist)->style->font->ascent + 1.5;
+      if (!GTK_WIDGET_VISIBLE (clist->hscrollbar))
+       {
+         gtk_widget_show (clist->hscrollbar);
+         gtk_widget_size_allocate (GTK_WIDGET (clist),
+                                   &GTK_WIDGET (clist)->allocation);
+       }
     }
 
-  /* Column widths */
+  gtk_signal_emit_by_name (GTK_OBJECT (vscrollbar->adjustment), "changed");
+  gtk_signal_emit_by_name (GTK_OBJECT (hscrollbar->adjustment), "changed");
 }
 
-
-/* focus functions */
-
 static void
-gtk_clist_draw_focus (GtkWidget *widget)
+vadjustment_changed (GtkAdjustment *adjustment,
+                    gpointer       data)
 {
   GtkCList *clist;
 
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  if (!GTK_WIDGET_DRAWABLE (widget))
-    return;
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
 
-  clist = GTK_CLIST (widget);
-  if (clist->focus_row >= 0)
-    gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
-                       0, ROW_TOP_YPIXEL(clist, clist->focus_row),
-                       clist->clist_window_width - 1,
-                       clist->row_height - 1);
+  clist = GTK_CLIST (data);
 }
 
 static void
-gtk_clist_set_focus_child (GtkContainer *container,
-                          GtkWidget    *child)
-{
-  g_return_if_fail (container != NULL);
-  g_return_if_fail (GTK_IS_CLIST (container));
-
-  if (child)
-    {
-      g_return_if_fail (GTK_IS_WIDGET (child));
-      GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
-    }
-
-  parent_class->set_focus_child (container, child);
-}
-
-static gint
-gtk_clist_focus_in (GtkWidget     *widget,
-                   GdkEventFocus *event)
+hadjustment_changed (GtkAdjustment *adjustment,
+                    gpointer       data)
 {
   GtkCList *clist;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
-  GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
-
-  clist = GTK_CLIST (widget);
-
-  if (clist->selection_mode == GTK_SELECTION_BROWSE &&
-      clist->selection == NULL && clist->focus_row > -1)
-    {
-      GList *list;
-
-      list = g_list_nth (clist->row_list, clist->focus_row);
-      if (list && GTK_CLIST_ROW (list)->selectable)
-       select_row (clist, clist->focus_row, -1, (GdkEvent *) event);
-      else
-       gtk_widget_draw_focus (widget);
-    }
-  else
-    gtk_widget_draw_focus (widget);
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
 
-  return FALSE;
+  clist = GTK_CLIST (data);
 }
 
-static gint
-gtk_clist_focus_out (GtkWidget     *widget,
-                    GdkEventFocus *event)
+static void
+vadjustment_value_changed (GtkAdjustment *adjustment,
+                          gpointer       data)
 {
   GtkCList *clist;
+  GdkRectangle area;
+  gint diff, value;
 
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
-  gtk_widget_draw_focus (widget);
-  
-  clist = GTK_CLIST (widget);
-
-  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
-    GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (GTK_IS_CLIST (data));
 
-  return FALSE;
-}
+  clist = GTK_CLIST (data);
 
-static void
-toggle_add_mode (GtkCList *clist)
-{
-  g_return_if_fail (clist != 0);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-  
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
-      clist->selection_mode != GTK_SELECTION_EXTENDED)
+  if (!GTK_WIDGET_DRAWABLE (clist))
     return;
 
-  gtk_clist_draw_focus (GTK_WIDGET (clist));
-  if (!GTK_CLIST_ADD_MODE (clist))
-    {
-      GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
-      gdk_gc_set_line_attributes (clist->xor_gc, 1,
-                                 GDK_LINE_ON_OFF_DASH, 0, 0);
-      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
-    }
-  else
-    {
-      GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
-      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
-      clist->anchor_state = GTK_STATE_SELECTED;
-    }
-  gtk_clist_draw_focus (GTK_WIDGET (clist));
-}
+  value = adjustment->value;
 
-static void
-toggle_focus_row (GtkCList *clist)
-{
-  g_return_if_fail (clist != 0);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  if (adjustment == gtk_range_get_adjustment (GTK_RANGE (clist->vscrollbar)))
+    {
+      if (value > -clist->voffset)
+       {
+         /* scroll down */
+         diff = value + clist->voffset;
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
-      clist->focus_row < 0 || clist->focus_row >= clist->rows)
-    return;
+         /* we have to re-draw the whole screen here... */
+         if (diff >= clist->clist_window_height)
+           {
+             clist->voffset = -value;
+             draw_rows (clist, NULL);
+             return;
+           }
 
-  switch (clist->selection_mode)
-    {
-    case  GTK_SELECTION_SINGLE:
-    case  GTK_SELECTION_MULTIPLE:
-      toggle_row (clist, clist->focus_row, 0, NULL);
-      break;
-    case GTK_SELECTION_EXTENDED:
-      g_list_free (clist->undo_selection);
-      g_list_free (clist->undo_unselection);
-      clist->undo_selection = NULL;
-      clist->undo_unselection = NULL;
+         if ((diff != 0) && (diff != clist->clist_window_height))
+           gdk_window_copy_area (clist->clist_window,
+                                 clist->fg_gc,
+                                 0, 0,
+                                 clist->clist_window,
+                                 0,
+                                 diff,
+                                 clist->clist_window_width,
+                                 clist->clist_window_height - diff);
 
-      clist->anchor = clist->focus_row;
-      clist->drag_pos = clist->focus_row;
-      clist->undo_anchor = clist->focus_row;
-      
-      if (GTK_CLIST_ADD_MODE (clist))
-       fake_toggle_row (clist, clist->focus_row);
+         area.x = 0;
+         area.y = clist->clist_window_height - diff;
+         area.width = clist->clist_window_width;
+         area.height = diff;
+       }
       else
-       GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist,clist->focus_row);
-
-      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
-      break;
-    default:
-      break;
-    }
-}
+       {
+         /* scroll up */
+         diff = -clist->voffset - value;
 
-static void
-move_focus_row (GtkCList      *clist,
-               GtkScrollType  scroll_type,
-               gfloat         position)
-{
-  GtkWidget *widget;
+         /* we have to re-draw the whole screen here... */
+         if (diff >= clist->clist_window_height)
+           {
+             clist->voffset = -value;
+             draw_rows (clist, NULL);
+             return;
+           }
 
-  g_return_if_fail (clist != 0);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+         if ((diff != 0) && (diff != clist->clist_window_height))
+           gdk_window_copy_area (clist->clist_window,
+                                 clist->fg_gc,
+                                 0, diff,
+                                 clist->clist_window,
+                                 0,
+                                 0,
+                                 clist->clist_window_width,
+                                 clist->clist_window_height - diff);
 
-  widget = GTK_WIDGET (clist);
+         area.x = 0;
+         area.y = 0;
+         area.width = clist->clist_window_width;
+         area.height = diff;
 
-  switch (scroll_type)
-    {
-    case GTK_SCROLL_STEP_BACKWARD:
-      if (clist->focus_row <= 0)
-       return;
-      gtk_clist_draw_focus (widget);
-      clist->focus_row--;
-      gtk_clist_draw_focus (widget);
-      break;
-    case GTK_SCROLL_STEP_FORWARD:
-      if (clist->focus_row >= clist->rows - 1)
-       return;
-      gtk_clist_draw_focus (widget);
-      clist->focus_row++;
-      gtk_clist_draw_focus (widget);
-      break;
-    case GTK_SCROLL_PAGE_BACKWARD:
-      if (clist->focus_row <= 0)
-       return;
-      gtk_clist_draw_focus (widget);
-      clist->focus_row = MAX (0, clist->focus_row -
-                             (2 * clist->clist_window_height -
-                              clist->row_height - CELL_SPACING) / 
-                             (2 * (clist->row_height + CELL_SPACING)));
-      gtk_clist_draw_focus (widget);
-      break;
-    case GTK_SCROLL_PAGE_FORWARD:
-      if (clist->focus_row >= clist->rows - 1)
-       return;
-      gtk_clist_draw_focus (widget);
-      clist->focus_row = MIN (clist->rows - 1, clist->focus_row + 
-                             (2 * clist->clist_window_height -
-                              clist->row_height - CELL_SPACING) / 
-                             (2 * (clist->row_height + CELL_SPACING)));
-      gtk_clist_draw_focus (widget);
-      break;
-    case GTK_SCROLL_JUMP:
-      if (position >= 0 && position <= 1)
-       {
-         gtk_clist_draw_focus (widget);
-         clist->focus_row = position * (clist->rows - 1);
-         gtk_clist_draw_focus (widget);
        }
-      break;
-    default:
-      break;
+
+      clist->voffset = -value;
+      if ((diff != 0) && (diff != clist->clist_window_height))
+       check_exposures (clist);
     }
+
+  draw_rows (clist, &area);
 }
 
 static void
-scroll_horizontal (GtkCList      *clist,
-                  GtkScrollType  scroll_type,
-                  gfloat         position)
+hadjustment_value_changed (GtkAdjustment *adjustment,
+                          gpointer       data)
 {
-  gint column = 0;
+  GtkCList *clist;
+  GdkRectangle area;
+  gint i;
+  gint y = 0;
+  gint diff = 0;
+  gint value;
 
-  g_return_if_fail (clist != 0);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  g_return_if_fail (adjustment != NULL);
+  g_return_if_fail (data != NULL);
+  g_return_if_fail (GTK_IS_CLIST (data));
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+  clist = GTK_CLIST (data);
+
+  if (!GTK_WIDGET_DRAWABLE (clist) ||
+      adjustment != gtk_range_get_adjustment (GTK_RANGE (clist->hscrollbar)))
     return;
 
-  switch (scroll_type)
+  value = adjustment->value;
+  
+  /* move the column buttons and resize windows */
+  for (i = 0; i < clist->columns; i++)
     {
-    case GTK_SCROLL_STEP_BACKWARD:
-      column = COLUMN_FROM_XPIXEL (clist, 0);
-      if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
-         && column > 0)
-       column--;
-      break;
-    case GTK_SCROLL_STEP_FORWARD:
-      column =  COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
-      if (column < 0)
-       return;
-      if (COLUMN_LEFT_XPIXEL (clist, column) + clist->column[column].area.width
-         + CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
-         column < clist->columns - 1)
-       column++;
-      break;
-    case GTK_SCROLL_PAGE_BACKWARD:
-    case GTK_SCROLL_PAGE_FORWARD:
-      return;
-    case GTK_SCROLL_JUMP:
-      if (position >= 0 && position <= 1)
-       column = position * (clist->columns - 1);
-      else
-       return;
-      break;
-    default:
-      break;
+      if (clist->column[i].button)
+       {
+         clist->column[i].button->allocation.x -= value + clist->hoffset;
+         
+         if (clist->column[i].button->window)
+           {
+             gdk_window_move (clist->column[i].button->window,
+                              clist->column[i].button->allocation.x,
+                              clist->column[i].button->allocation.y);
+             
+             if (clist->column[i].window)
+               gdk_window_move (clist->column[i].window,
+                                clist->column[i].button->allocation.x +
+                                clist->column[i].button->allocation.width - 
+                                (DRAG_WIDTH / 2), 0); 
+           }
+       }
     }
 
-  if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
-    gtk_clist_moveto (clist, -1, column, 0, 0);
-  else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
-          + clist->column[column].area.width > clist->clist_window_width)
+  if (value > -clist->hoffset)
     {
-      if (column == clist->columns - 1)
-       gtk_clist_moveto (clist, -1, column, 0, 0);
-      else
-       gtk_clist_moveto (clist, -1, column, 0, 1);
-    }
-}
-
-static void
-scroll_vertical (GtkCList      *clist,
-                GtkScrollType  scroll_type,
-                gfloat         position)
-{
-  gint old_focus_row;
-
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+      /* scroll right */
+      diff = value + clist->hoffset;
+      
+      clist->hoffset = -value;
+      
+      /* we have to re-draw the whole screen here... */
+      if (diff >= clist->clist_window_width)
+       {
+         draw_rows (clist, NULL);
+         return;
+       }
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
-    return;
+      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
+         GTK_CLIST_ADD_MODE (clist))
+       {
+         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+             
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                             clist->clist_window_width - 1,
+                             clist->row_height - 1);
+       }
+      gdk_window_copy_area (clist->clist_window,
+                           clist->fg_gc,
+                           0, 0,
+                           clist->clist_window,
+                           diff,
+                           0,
+                           clist->clist_window_width - diff,
+                           clist->clist_window_height);
 
-  switch (clist->selection_mode)
+      area.x = clist->clist_window_width - diff;
+    }
+  else
     {
-    case GTK_SELECTION_EXTENDED:
-      if (clist->anchor >= 0)
+      /* scroll left */
+      if (!(diff = -clist->hoffset - value))
        return;
 
-    case GTK_SELECTION_BROWSE:
+      clist->hoffset = -value;
+      
+      /* we have to re-draw the whole screen here... */
+      if (diff >= clist->clist_window_width)
+       {
+         draw_rows (clist, NULL);
+         return;
+       }
+      
+      if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
+         GTK_CLIST_ADD_MODE (clist))
+       {
+         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+         
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
+                             clist->clist_window_width - 1,
+                             clist->row_height - 1);
+       }
 
-      old_focus_row = clist->focus_row;
-      move_focus_row (clist, scroll_type, position);
+      gdk_window_copy_area (clist->clist_window,
+                           clist->fg_gc,
+                           diff, 0,
+                           clist->clist_window,
+                           0,
+                           0,
+                           clist->clist_window_width - diff,
+                           clist->clist_window_height);
+         
+      area.x = 0;
+    }
 
-      if (old_focus_row != clist->focus_row)
+  area.y = 0;
+  area.width = diff;
+  area.height = clist->clist_window_height;
+
+  check_exposures (clist);
+
+  if (GTK_WIDGET_HAS_FOCUS (clist) && !GTK_CLIST_CHILD_HAS_FOCUS (clist))
+    {
+      if (GTK_CLIST_ADD_MODE (clist))
        {
-         if (clist->selection_mode == GTK_SELECTION_BROWSE)
-           unselect_row (clist,old_focus_row, -1, NULL);
-         else if (!GTK_CLIST_ADD_MODE (clist))
-           {
-             gtk_clist_unselect_all (clist);
-             clist->undo_anchor = old_focus_row;
-           }
+         gint focus_row;
+         
+         focus_row = clist->focus_row;
+         clist->focus_row = -1;
+         draw_rows (clist, &area);
+         clist->focus_row = focus_row;
+         
+         gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
+                             FALSE, 0, y, clist->clist_window_width - 1,
+                             clist->row_height - 1);
+         return;
        }
-
-      switch (gtk_clist_row_is_visible (clist, clist->focus_row))
+      else
        {
-       case GTK_VISIBILITY_NONE:
-         if (old_focus_row != clist->focus_row &&
-             !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
-           select_row (clist, clist->focus_row, -1, NULL);
-         switch (scroll_type)
+         gint x0;
+         gint x1;
+         
+         if (area.x == 0)
            {
-           case GTK_SCROLL_STEP_BACKWARD:
-           case GTK_SCROLL_PAGE_BACKWARD:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-             break;
-           case GTK_SCROLL_STEP_FORWARD:
-           case GTK_SCROLL_PAGE_FORWARD:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-             break;
-           case GTK_SCROLL_JUMP:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
-             break;
-           default:
-             break;
+             x0 = clist->clist_window_width - 1;
+             x1 = diff;
            }
-         break;
-
-       case GTK_VISIBILITY_PARTIAL:
-         switch (scroll_type)
+         else
            {
-           case GTK_SCROLL_STEP_BACKWARD:
-           case GTK_SCROLL_PAGE_BACKWARD:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-             break;
-           case GTK_SCROLL_STEP_FORWARD:
-           case GTK_SCROLL_PAGE_FORWARD:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-             break;
-           case GTK_SCROLL_JUMP:
-             gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
-             break;
-           default:
-             break;
-           }
-
-       default:
-         if (old_focus_row != clist->focus_row &&
-             !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
-               GTK_CLIST_ADD_MODE (clist)))
-           select_row (clist, clist->focus_row, -1, NULL);
-         break;
-       }
-      break;
-
-    default:
-      move_focus_row (clist, scroll_type, position);
-
-      if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
-         clist->clist_window_height)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-      else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-      break;
+             x0 = 0;
+             x1 = area.x - 1;
+           }
+         
+         y = ROW_TOP_YPIXEL (clist, clist->focus_row);
+         gdk_draw_line (clist->clist_window, clist->xor_gc,
+                        x0, y + 1, x0, y + clist->row_height - 2);
+         gdk_draw_line (clist->clist_window, clist->xor_gc,
+                        x1, y + 1, x1, y + clist->row_height - 2);
+         
+       }
     }
+  draw_rows (clist, &area);
 }
 
 static void
-set_anchor (GtkCList *clist,
-           gboolean  add_mode,
-           gint      anchor,
-           gint      undo_anchor)
+check_exposures (GtkCList *clist)
 {
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-  
-  if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor >= 0)
-    return;
+  GdkEvent *event;
 
-  g_list_free (clist->undo_selection);
-  g_list_free (clist->undo_unselection);
-  clist->undo_selection = NULL;
-  clist->undo_unselection = NULL;
+  if (!GTK_WIDGET_REALIZED (clist))
+    return;
 
-  if (add_mode)
-    fake_toggle_row (clist, anchor);
-  else
+  /* Make sure graphics expose events are processed before scrolling
+   * again */
+  while ((event = gdk_event_get_graphics_expose (clist->clist_window)) != NULL)
     {
-      GTK_CLIST_CLASS_FW (clist)->fake_unselect_all (clist, anchor);
-      clist->anchor_state = GTK_STATE_SELECTED;
+      gtk_widget_event (GTK_WIDGET (clist), event);
+      if (event->expose.count == 0)
+       {
+         gdk_event_free (event);
+         break;
+       }
+      gdk_event_free (event);
     }
-
-  clist->anchor = anchor;
-  clist->drag_pos = anchor;
-  clist->undo_anchor = undo_anchor;
 }
 
-static void
-resync_selection (GtkCList *clist,
-                 GdkEvent *event)
+/* 
+ * Memory Allocation/Distruction Routines for GtkCList stuctures
+ *
+ * functions:
+ *   columns_new
+ *   column_title_new
+ *   columns_delete
+ *   row_new
+ *   row_delete
+ */
+static GtkCListColumn *
+columns_new (GtkCList *clist)
 {
+  GtkCListColumn *column;
   gint i;
-  gint e;
-  gint row;
-  gboolean thaw = FALSE;
-  GList *list;
-  GtkCListRow *clist_row;
 
-  if (clist->anchor < 0)
-    return;
+  column = g_new (GtkCListColumn, clist->columns);
 
-  if (!GTK_CLIST_FROZEN (clist))
+  for (i = 0; i < clist->columns; i++)
     {
-      GTK_CLIST_SET_FLAG (clist, CLIST_FROZEN);
-      thaw = TRUE;
+      column[i].area.x = 0;
+      column[i].area.y = 0;
+      column[i].area.width = 0;
+      column[i].area.height = 0;
+      column[i].title = NULL;
+      column[i].button = NULL;
+      column[i].window = NULL;
+      column[i].width = 0;
+      column[i].min_width = -1;
+      column[i].max_width = -1;
+      column[i].visible = TRUE;
+      column[i].width_set = FALSE;
+      column[i].resizeable = TRUE;
+      column[i].auto_resize = FALSE;
+      column[i].justification = GTK_JUSTIFY_LEFT;
     }
 
-  i = MIN (clist->anchor, clist->drag_pos);
-  e = MAX (clist->anchor, clist->drag_pos);
-
-  if (clist->undo_selection)
-    {
-      list = clist->selection;
-      clist->selection = clist->undo_selection;
-      clist->selection_end = g_list_last (clist->selection);
-      clist->undo_selection = list;
-      list = clist->selection;
-      while (list)
-       {
-         row = GPOINTER_TO_INT (list->data);
-         list = list->next;
-         if (row < i || row > e)
-           {
-             clist_row = g_list_nth (clist->row_list, row)->data;
-             if (clist_row->selectable)
-               {
-                 clist_row->state = GTK_STATE_SELECTED;
-                 unselect_row (clist, row, -1, event);
-                 clist->undo_selection = g_list_prepend
-                   (clist->undo_selection, GINT_TO_POINTER (row));
-               }
-           }
-       }
-    }    
-
-  for (list = g_list_nth (clist->row_list, i); i <= e; i++, list = list->next)
-    if (GTK_CLIST_ROW (list)->selectable)
-      {
-       if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
-         {
-           if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
-             {
-               GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
-               unselect_row (clist, i, -1, event);
-               clist->undo_selection = g_list_prepend (clist->undo_selection,
-                                                       GINT_TO_POINTER (i));
-             }
-         }
-       else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
-         {
-           GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
-           clist->undo_unselection = g_list_prepend (clist->undo_unselection,
-                                                     GINT_TO_POINTER (i));
-         }
-      }
-
-  for (list = clist->undo_unselection; list; list = list->next)
-    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                    GPOINTER_TO_INT (list->data), -1, event);
+  return column;
+}
 
-  clist->anchor = -1;
-  clist->drag_pos = -1;
+static void
+column_title_new (GtkCList    *clist,
+                 gint         column,
+                 const gchar *title)
+{
+  if (clist->column[column].title)
+    g_free (clist->column[column].title);
 
-  if (thaw)
-    GTK_CLIST_UNSET_FLAG (clist, CLIST_FROZEN);
+  clist->column[column].title = g_strdup (title);
 }
 
 static void
-update_extended_selection (GtkCList *clist,
-                          gint      row)
+columns_delete (GtkCList *clist)
 {
   gint i;
-  GList *list;
-  GdkRectangle area;
-  gint s1 = -1;
-  gint s2 = -1;
-  gint e1 = -1;
-  gint e2 = -1;
-  gint y1 = clist->clist_window_height;
-  gint y2 = clist->clist_window_height;
-  gint h1 = 0;
-  gint h2 = 0;
-  gint top;
 
-  if (clist->selection_mode != GTK_SELECTION_EXTENDED || clist->anchor == -1)
-    return;
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].title)
+      g_free (clist->column[i].title);
+      
+  g_free (clist->column);
+}
 
-  if (row < 0)
-    row = 0;
-  if (row >= clist->rows)
-    row = clist->rows - 1;
+static GtkCListRow *
+row_new (GtkCList *clist)
+{
+  int i;
+  GtkCListRow *clist_row;
 
-  /* extending downwards */
-  if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
-    {
-      s2 = clist->drag_pos + 1;
-      e2 = row;
-    }
-  /* extending upwards */
-  else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
+  clist_row = g_chunk_new (GtkCListRow, clist->row_mem_chunk);
+  clist_row->cell = g_chunk_new (GtkCell, clist->cell_mem_chunk);
+
+  for (i = 0; i < clist->columns; i++)
     {
-      s2 = row;
-      e2 = clist->drag_pos - 1;
+      clist_row->cell[i].type = GTK_CELL_EMPTY;
+      clist_row->cell[i].vertical = 0;
+      clist_row->cell[i].horizontal = 0;
+      clist_row->cell[i].style = NULL;
     }
-  else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
+
+  clist_row->fg_set = FALSE;
+  clist_row->bg_set = FALSE;
+  clist_row->style = NULL;
+  clist_row->selectable = TRUE;
+  clist_row->state = GTK_STATE_NORMAL;
+  clist_row->data = NULL;
+  clist_row->destroy = NULL;
+
+  return clist_row;
+}
+
+static void
+row_delete (GtkCList    *clist,
+           GtkCListRow *clist_row)
+{
+  gint i;
+
+  for (i = 0; i < clist->columns; i++)
     {
-      e1 = clist->drag_pos;
-      /* row and drag_pos on different sides of anchor :
-        take back the selection between anchor and drag_pos,
-         select between anchor and row */
-      if (row < clist->anchor)
+      GTK_CLIST_CLASS_FW (clist)->set_cell_contents
+       (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
+      if (clist_row->cell[i].style)
        {
-         s1 = clist->anchor + 1;
-         s2 = row;
-         e2 = clist->anchor - 1;
+         if (GTK_WIDGET_REALIZED (clist))
+           gtk_style_detach (clist_row->cell[i].style);
+         gtk_style_unref (clist_row->cell[i].style);
        }
-      /* take back the selection between anchor and drag_pos */
-      else
-       s1 = row + 1;
     }
-  else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
+
+  if (clist_row->style)
     {
-      s1 = clist->drag_pos;
-      /* row and drag_pos on different sides of anchor :
-        take back the selection between anchor and drag_pos,
-         select between anchor and row */
-      if (row > clist->anchor)
-       {
-         e1 = clist->anchor - 1;
-         s2 = clist->anchor + 1;
-         e2 = row;
-       }
-      /* take back the selection between anchor and drag_pos */
-      else
-       e1 = row - 1;
+      if (GTK_WIDGET_REALIZED (clist))
+        gtk_style_detach (clist_row->style);
+      gtk_style_unref (clist_row->style);
     }
 
-  clist->drag_pos = row;
+  if (clist_row->destroy)
+    clist_row->destroy (clist_row->data);
+
+  g_mem_chunk_free (clist->cell_mem_chunk, clist_row->cell);
+  g_mem_chunk_free (clist->row_mem_chunk, clist_row);
+}
 
-  area.x = 0;
-  area.width = clist->clist_window_width;
+/* FOCUS FUNCTIONS
+ *   gtk_clist_focus
+ *   gtk_clist_draw_focus
+ *   gtk_clist_focus_in
+ *   gtk_clist_focus_out
+ *   gtk_clist_set_focus_child
+ *   title_focus
+ */
+static gint
+gtk_clist_focus (GtkContainer     *container,
+                GtkDirectionType  direction)
+{
+  GtkCList *clist;
+  GtkWidget *focus_child;
+  gint old_row;
 
-  /* restore the elements between s1 and e1 */
-  if (s1 >= 0)
-    {
-      for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
-          i++, list = list->next)
-       if (GTK_CLIST_ROW (list)->selectable)
-         {
-           if (GTK_CLIST_CLASS_FW (clist)->selection_find (clist, i, list))
-             GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
-           else
-             GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
-         }
+  g_return_val_if_fail (container != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
 
-      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+  if (!GTK_WIDGET_SENSITIVE (container))
+    return FALSE;
+  
+  clist = GTK_CLIST (container);
+  focus_child = container->focus_child;
+  old_row = clist->focus_row;
 
-      if (top + clist->row_height <= 0)
+  switch (direction)
+    {
+    case GTK_DIR_LEFT:
+    case GTK_DIR_RIGHT:
+      if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
+         (!focus_child || (focus_child && focus_child != clist->vscrollbar && 
+                           focus_child != clist->hscrollbar)))
        {
-         area.y = 0;
-         area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
-         draw_rows (clist, &area);
-         gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-       }
-      else if (top >= clist->clist_window_height)
+         if (title_focus (clist, direction))
+           return TRUE;
+         gtk_container_set_focus_child (container, NULL);
+         return FALSE;
+        }
+      gtk_widget_grab_focus (GTK_WIDGET (container));
+      return TRUE;
+    case GTK_DIR_DOWN:
+    case GTK_DIR_TAB_FORWARD:
+      if (GTK_CLIST_CHILD_HAS_FOCUS (clist) && 
+         (!focus_child || (focus_child != clist->vscrollbar &&
+                           focus_child != clist->hscrollbar))) 
        {
-         area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
-         area.height = clist->clist_window_height - area.y;
-         draw_rows (clist, &area);
-         gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-       }
-      else if (top < 0)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-      else if (top + clist->row_height > clist->clist_window_height)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+         gboolean tf = FALSE;
 
-      y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
-      h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
-    }
+         if (((focus_child && direction == GTK_DIR_DOWN) ||
+              !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
+             && clist->rows)
+           {
+             if (clist->focus_row < 0)
+               {
+                 clist->focus_row = 0;
 
-  /* extend the selection between s2 and e2 */
-  if (s2 >= 0)
-    {
-      for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
-          i++, list = list->next)
-       if (GTK_CLIST_ROW (list)->selectable &&
-           GTK_CLIST_ROW (list)->state != clist->anchor_state)
-         GTK_CLIST_ROW (list)->state = clist->anchor_state;
+                 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+                      clist->selection_mode == GTK_SELECTION_EXTENDED) &&
+                     !clist->selection)
+                   gtk_signal_emit (GTK_OBJECT (clist),
+                                    clist_signals[SELECT_ROW],
+                                    clist->focus_row, -1, NULL);
+               }
+             gtk_widget_grab_focus (GTK_WIDGET (container));
+             return TRUE;
+           }
 
-      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
+         if (tf)
+           return TRUE;
+       }
+      
+      GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
 
-      if (top + clist->row_height <= 0)
+      if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
+          (focus_child != clist->vscrollbar &&
+           focus_child != clist->hscrollbar)) &&
+         GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
+         GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
        {
-         area.y = 0;
-         area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
-         draw_rows (clist, &area);
-         gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+         gtk_widget_grab_focus (clist->vscrollbar);
+         return TRUE;
        }
-      else if (top >= clist->clist_window_height)
+
+      if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child || 
+          focus_child != clist->hscrollbar) &&
+         GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
+         GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
        {
-         area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
-         area.height = clist->clist_window_height - area.y;
-         draw_rows (clist, &area);
-         gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+         gtk_widget_grab_focus (clist->hscrollbar);
+         return TRUE;
+       }
+      break;
+    case GTK_DIR_UP:
+    case GTK_DIR_TAB_BACKWARD:
+      if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
+         GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
+         GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
+       {
+         gtk_widget_grab_focus (clist->hscrollbar);
+         return TRUE;
+       }
+       
+      if ((!focus_child || focus_child == clist->hscrollbar) &&
+         GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
+         GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
+         GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
+       {
+         gtk_widget_grab_focus (clist->vscrollbar);
+         return TRUE;
        }
-      else if (top < 0)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-      else if (top + clist->row_height > clist->clist_window_height)
-       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-
-      y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
-      h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
-    }
-
-  area.y = MAX (0, MIN (y1, y2));
-  if (area.y > clist->clist_window_height)
-    area.y = 0;
-  area.height = MIN (clist->clist_window_height, h1 + h2);
-  if (s1 >= 0 && s2 >= 0)
-    area.height += (clist->row_height + CELL_SPACING);
-  draw_rows (clist, &area);
-}
 
-static void
-start_selection (GtkCList *clist)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+      if ((!focus_child || focus_child == clist->hscrollbar ||
+          focus_child == clist->vscrollbar) &&
+         GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
+       {
+         if (clist->focus_row < 0)
+           {
+             clist->focus_row = 0;
+             if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
+                  clist->selection_mode == GTK_SELECTION_EXTENDED) &&
+                 !clist->selection)
+               gtk_signal_emit (GTK_OBJECT (clist),
+                                clist_signals[SELECT_ROW],
+                                clist->focus_row, -1, NULL);
+           }
+         gtk_widget_grab_focus (GTK_WIDGET (container));
+         return TRUE;
+       }
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
-    return;
+      GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
 
-  set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
-             clist->focus_row);
-}
+      if (title_focus (clist, direction))
+       return TRUE;
 
-static void
-end_selection (GtkCList *clist)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+      break;
+    default:
+      break;
+    }
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_FOCUS (clist)) ||
-      clist->anchor == -1)
-    return;
-  
-  GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+  gtk_container_set_focus_child (container, NULL);
+  return FALSE;
 }
 
 static void
-extend_selection (GtkCList      *clist,
-                 GtkScrollType  scroll_type,
-                 gfloat         position,
-                 gboolean       auto_start_selection)
+gtk_clist_draw_focus (GtkWidget *widget)
 {
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  GtkCList *clist;
 
-  if ((gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist)) ||
-      clist->selection_mode != GTK_SELECTION_EXTENDED)
-    return;
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_CLIST (widget));
 
-  if (auto_start_selection)
-    set_anchor (clist, GTK_CLIST_ADD_MODE (clist), clist->focus_row,
-               clist->focus_row);
-  else if (clist->anchor == -1)
+  if (!GTK_WIDGET_DRAWABLE (widget))
     return;
 
-  move_focus_row (clist, scroll_type, position);
-
-  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
-      clist->clist_window_height)
-    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
-  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
-    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
-
-  update_extended_selection (clist, clist->focus_row);
+  clist = GTK_CLIST (widget);
+  if (clist->focus_row >= 0)
+    gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
+                       0, ROW_TOP_YPIXEL(clist, clist->focus_row),
+                       clist->clist_window_width - 1,
+                       clist->row_height - 1);
 }
 
-static void
-abort_column_resize (GtkCList *clist)
+static gint
+gtk_clist_focus_in (GtkWidget     *widget,
+                   GdkEventFocus *event)
 {
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  GtkCList *clist;
 
-  if (!GTK_CLIST_IN_DRAG (clist))
-    return;
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
 
-  GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
-  gtk_grab_remove (GTK_WIDGET (clist));
-  gdk_pointer_ungrab (GDK_CURRENT_TIME);
-  clist->drag_pos = -1;
+  GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
+  GTK_CLIST_UNSET_FLAG (widget, CLIST_CHILD_HAS_FOCUS);
 
-  if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
-    draw_xor_line (clist);
+  clist = GTK_CLIST (widget);
 
-  if (GTK_CLIST_ADD_MODE (clist))
+  if (clist->selection_mode == GTK_SELECTION_BROWSE &&
+      clist->selection == NULL && clist->focus_row > -1)
     {
-      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
-      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
+      GList *list;
+
+      list = g_list_nth (clist->row_list, clist->focus_row);
+      if (list && GTK_CLIST_ROW (list)->selectable)
+       gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                        clist->focus_row, -1, event);
+      else
+       gtk_widget_draw_focus (widget);
     }
+  else
+    gtk_widget_draw_focus (widget);
+
+  return FALSE;
 }
 
 static gint
-gtk_clist_key_press (GtkWidget   * widget,
-                    GdkEventKey * event)
+gtk_clist_focus_out (GtkWidget     *widget,
+                    GdkEventFocus *event)
 {
+  GtkCList *clist;
+
   g_return_val_if_fail (widget != NULL, FALSE);
   g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
   g_return_val_if_fail (event != NULL, FALSE);
 
-  if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
-      GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
-    return TRUE;
+  GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
+  gtk_widget_draw_focus (widget);
+  
+  clist = GTK_CLIST (widget);
 
-  switch (event->keyval)
-    {
-    case GDK_Tab:
-    case GDK_ISO_Left_Tab:
-      if (event->state & GDK_SHIFT_MASK)
-       return gtk_container_focus (GTK_CONTAINER (widget),
-                                   GTK_DIR_TAB_BACKWARD);
-      else
-       return gtk_container_focus (GTK_CONTAINER (widget),
-                                   GTK_DIR_TAB_FORWARD);
+  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
+    GTK_CLIST_CLASS_FW (widget)->resync_selection (clist, (GdkEvent *) event);
 
-    default:
-      break;
-    }
-  
   return FALSE;
 }
 
+static void
+gtk_clist_set_focus_child (GtkContainer *container,
+                          GtkWidget    *child)
+{
+  g_return_if_fail (container != NULL);
+  g_return_if_fail (GTK_IS_CLIST (container));
+
+  if (child)
+    {
+      g_return_if_fail (GTK_IS_WIDGET (child));
+      GTK_CLIST_SET_FLAG (GTK_CLIST (container), CLIST_CHILD_HAS_FOCUS);
+    }
+
+  parent_class->set_focus_child (container, child);
+}
+
 static gboolean
-title_focus (GtkCList * clist,
-            gint       dir)
+title_focus (GtkCList *clist,
+            gint      dir)
 {
   GtkWidget *focus_child;
   gboolean return_val = FALSE;
@@ -6046,154 +6544,134 @@ title_focus (GtkCList * clist,
   return return_val;
 }
 
-static gint
-gtk_clist_focus (GtkContainer     * container,
-                GtkDirectionType   direction)
+/* SCROLLING FUNCTIONS
+ *   move_focus_row
+ *   scroll_horizontal
+ *   scroll_vertical
+ */
+static void
+move_focus_row (GtkCList      *clist,
+               GtkScrollType  scroll_type,
+               gfloat         position)
 {
-  GtkCList *clist;
-  GtkWidget *focus_child;
-  gint old_row;
+  GtkWidget *widget;
 
-  g_return_val_if_fail (container != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (container), FALSE);
+  g_return_if_fail (clist != 0);
+  g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (!GTK_WIDGET_SENSITIVE (container))
-    return FALSE;
-  
-  clist = GTK_CLIST (container);
-  focus_child = container->focus_child;
-  old_row = clist->focus_row;
+  widget = GTK_WIDGET (clist);
 
-  switch (direction)
+  switch (scroll_type)
     {
-    case GTK_DIR_LEFT:
-    case GTK_DIR_RIGHT:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         (!focus_child || (focus_child && focus_child != clist->vscrollbar && 
-                           focus_child != clist->hscrollbar)))
-       {
-         if (title_focus (clist, direction))
-           return TRUE;
-         gtk_container_set_focus_child (container, NULL);
-         return FALSE;
-        }
-      gtk_widget_grab_focus (GTK_WIDGET (container));
-      return TRUE;
-    case GTK_DIR_DOWN:
-    case GTK_DIR_TAB_FORWARD:
-      if (GTK_CLIST_CHILD_HAS_FOCUS (clist) && 
-         (!focus_child || (focus_child != clist->vscrollbar &&
-                           focus_child != clist->hscrollbar))) 
-       {
-         gboolean tf = FALSE;
-
-         if (((focus_child && direction == GTK_DIR_DOWN) ||
-              !(tf = title_focus (clist, GTK_DIR_TAB_FORWARD)))
-             && clist->rows)
-           {
-             if (clist->focus_row < 0)
-               {
-                 clist->focus_row = 0;
-
-                 if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
-                      clist->selection_mode == GTK_SELECTION_EXTENDED) &&
-                     !clist->selection)
-                   select_row (clist, clist->focus_row, -1, NULL);
-               }
-             gtk_widget_grab_focus (GTK_WIDGET (container));
-             return TRUE;
-           }
-
-         if (tf)
-           return TRUE;
-       }
-      
-      GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
-
-      if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child ||
-          (focus_child != clist->vscrollbar &&
-           focus_child != clist->hscrollbar)) &&
-         GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
-         GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
-       {
-         gtk_widget_grab_focus (clist->vscrollbar);
-         return TRUE;
-       }
-
-      if ((!GTK_CLIST_CHILD_HAS_FOCUS (clist) || !focus_child || 
-          focus_child != clist->hscrollbar) &&
-         GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
-         GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
-       {
-         gtk_widget_grab_focus (clist->hscrollbar);
-         return TRUE;
-       }
+    case GTK_SCROLL_STEP_BACKWARD:
+      if (clist->focus_row <= 0)
+       return;
+      gtk_clist_draw_focus (widget);
+      clist->focus_row--;
+      gtk_clist_draw_focus (widget);
       break;
-    case GTK_DIR_UP:
-    case GTK_DIR_TAB_BACKWARD:
-      if (!focus_child && GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_WIDGET_VISIBLE (clist->hscrollbar) &&
-         GTK_WIDGET_CAN_FOCUS (clist->hscrollbar))
-       {
-         gtk_widget_grab_focus (clist->hscrollbar);
-         return TRUE;
-       }
-       
-      if ((!focus_child || focus_child == clist->hscrollbar) &&
-         GTK_CLIST_CHILD_HAS_FOCUS (clist) &&
-         GTK_WIDGET_VISIBLE (clist->vscrollbar) &&
-         GTK_WIDGET_CAN_FOCUS (clist->vscrollbar))
-       {
-         gtk_widget_grab_focus (clist->vscrollbar);
-         return TRUE;
-       }
-
-      if ((!focus_child || focus_child == clist->hscrollbar ||
-          focus_child == clist->vscrollbar) &&
-         GTK_CLIST_CHILD_HAS_FOCUS (clist) && clist->rows)
+    case GTK_SCROLL_STEP_FORWARD:
+      if (clist->focus_row >= clist->rows - 1)
+       return;
+      gtk_clist_draw_focus (widget);
+      clist->focus_row++;
+      gtk_clist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_PAGE_BACKWARD:
+      if (clist->focus_row <= 0)
+       return;
+      gtk_clist_draw_focus (widget);
+      clist->focus_row = MAX (0, clist->focus_row -
+                             (2 * clist->clist_window_height -
+                              clist->row_height - CELL_SPACING) / 
+                             (2 * (clist->row_height + CELL_SPACING)));
+      gtk_clist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_PAGE_FORWARD:
+      if (clist->focus_row >= clist->rows - 1)
+       return;
+      gtk_clist_draw_focus (widget);
+      clist->focus_row = MIN (clist->rows - 1, clist->focus_row + 
+                             (2 * clist->clist_window_height -
+                              clist->row_height - CELL_SPACING) / 
+                             (2 * (clist->row_height + CELL_SPACING)));
+      gtk_clist_draw_focus (widget);
+      break;
+    case GTK_SCROLL_JUMP:
+      if (position >= 0 && position <= 1)
        {
-         if (clist->focus_row < 0)
-           {
-             clist->focus_row = 0;
-             if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
-                  clist->selection_mode == GTK_SELECTION_EXTENDED) &&
-                 !clist->selection)
-               select_row (clist, clist->focus_row, -1, NULL);
-           }
-         gtk_widget_grab_focus (GTK_WIDGET (container));
-         return TRUE;
+         gtk_clist_draw_focus (widget);
+         clist->focus_row = position * (clist->rows - 1);
+         gtk_clist_draw_focus (widget);
        }
-
-      GTK_CLIST_SET_FLAG (clist, CLIST_CHILD_HAS_FOCUS);
-
-      if (title_focus (clist, direction))
-       return TRUE;
-
       break;
-
     default:
       break;
     }
-
-  gtk_container_set_focus_child (container, NULL);
-  return FALSE;
 }
 
-void
-gtk_clist_unselect_all (GtkCList * clist)
+static void
+scroll_horizontal (GtkCList      *clist,
+                  GtkScrollType  scroll_type,
+                  gfloat         position)
 {
-  g_return_if_fail (clist != NULL);
+  gint column = 0;
+
+  g_return_if_fail (clist != 0);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  GTK_CLIST_CLASS_FW (clist)->unselect_all (clist);
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    return;
+
+  switch (scroll_type)
+    {
+    case GTK_SCROLL_STEP_BACKWARD:
+      column = COLUMN_FROM_XPIXEL (clist, 0);
+      if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
+         && column > 0)
+       column--;
+      break;
+    case GTK_SCROLL_STEP_FORWARD:
+      column =  COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
+      if (column < 0)
+       return;
+      if (COLUMN_LEFT_XPIXEL (clist, column) + clist->column[column].area.width
+         + CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
+         column < clist->columns - 1)
+       column++;
+      break;
+    case GTK_SCROLL_PAGE_BACKWARD:
+    case GTK_SCROLL_PAGE_FORWARD:
+      return;
+    case GTK_SCROLL_JUMP:
+      if (position >= 0 && position <= 1)
+       column = position * (clist->columns - 1);
+      else
+       return;
+      break;
+    default:
+      break;
+    }
+
+  if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
+    gtk_clist_moveto (clist, -1, column, 0, 0);
+  else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
+          + clist->column[column].area.width > clist->clist_window_width)
+    {
+      if (column == clist->columns - 1)
+       gtk_clist_moveto (clist, -1, column, 0, 0);
+      else
+       gtk_clist_moveto (clist, -1, column, 0, 1);
+    }
 }
 
 static void
-real_unselect_all (GtkCList * clist)
+scroll_vertical (GtkCList      *clist,
+                GtkScrollType  scroll_type,
+                gfloat         position)
 {
-  GList *list;
-  gint i;
+  gint old_focus_row;
+
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
@@ -6202,169 +6680,164 @@ real_unselect_all (GtkCList * clist)
 
   switch (clist->selection_mode)
     {
+    case GTK_SELECTION_EXTENDED:
+      if (clist->anchor >= 0)
+       return;
     case GTK_SELECTION_BROWSE:
-      if (clist->focus_row >= 0)
+
+      old_focus_row = clist->focus_row;
+      move_focus_row (clist, scroll_type, position);
+
+      if (old_focus_row != clist->focus_row)
        {
-         select_row (clist, clist->focus_row, -1, NULL);
-         return;
+         if (clist->selection_mode == GTK_SELECTION_BROWSE)
+           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
+                            old_focus_row, -1, NULL);
+         else if (!GTK_CLIST_ADD_MODE (clist))
+           {
+             gtk_clist_unselect_all (clist);
+             clist->undo_anchor = old_focus_row;
+           }
        }
-      break;
-
-    case GTK_SELECTION_EXTENDED:
-      g_list_free (clist->undo_selection);
-      g_list_free (clist->undo_unselection);
-      clist->undo_selection = NULL;
-      clist->undo_unselection = NULL;
 
-      clist->anchor = -1;
-      clist->drag_pos = -1;
-      clist->undo_anchor = clist->focus_row;
+      switch (gtk_clist_row_is_visible (clist, clist->focus_row))
+       {
+       case GTK_VISIBILITY_NONE:
+         if (old_focus_row != clist->focus_row &&
+             !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
+               GTK_CLIST_ADD_MODE (clist)))
+           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                            clist->focus_row, -1, NULL);
+         switch (scroll_type)
+           {
+           case GTK_SCROLL_STEP_BACKWARD:
+           case GTK_SCROLL_PAGE_BACKWARD:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+             break;
+           case GTK_SCROLL_STEP_FORWARD:
+           case GTK_SCROLL_PAGE_FORWARD:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+             break;
+           case GTK_SCROLL_JUMP:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+             break;
+           default:
+             break;
+           }
+         break;
+       case GTK_VISIBILITY_PARTIAL:
+         switch (scroll_type)
+           {
+           case GTK_SCROLL_STEP_BACKWARD:
+           case GTK_SCROLL_PAGE_BACKWARD:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+             break;
+           case GTK_SCROLL_STEP_FORWARD:
+           case GTK_SCROLL_PAGE_FORWARD:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+             break;
+           case GTK_SCROLL_JUMP:
+             gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
+             break;
+           default:
+             break;
+           }
+       default:
+         if (old_focus_row != clist->focus_row &&
+             !(clist->selection_mode == GTK_SELECTION_EXTENDED &&
+               GTK_CLIST_ADD_MODE (clist)))
+           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
+                            clist->focus_row, -1, NULL);
+         break;
+       }
       break;
-
     default:
-      break;
-    }
-
-  list = clist->selection;
+      move_focus_row (clist, scroll_type, position);
 
-  while (list)
-    {
-      i = GPOINTER_TO_INT (list->data);
-      list = list->next;
-      unselect_row (clist, i, -1, NULL);
+      if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
+         clist->clist_window_height)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
+      else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
+       gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
+      break;
     }
 }
 
+/* PUBLIC SORTING FUNCTIONS
+ * gtk_clist_sort
+ * gtk_clist_set_compare_func
+ * gtk_clist_set_auto_sort
+ * gtk_clist_set_sort_type
+ * gtk_clist_set_sort_column
+ */
 void
-gtk_clist_select_all (GtkCList * clist)
+gtk_clist_sort (GtkCList *clist)
 {
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  GTK_CLIST_CLASS_FW (clist)->select_all (clist);
+  GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
 }
 
-static void
-real_select_all (GtkCList * clist)
+void
+gtk_clist_set_compare_func (GtkCList            *clist,
+                           GtkCListCompareFunc  cmp_func)
 {
-  GList *list;
-  gint i;
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
 
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
-    return;
-
-  switch (clist->selection_mode)
-    {
-    case GTK_SELECTION_SINGLE:
-    case GTK_SELECTION_BROWSE:
-      return;
-
-    case GTK_SELECTION_EXTENDED:
-      g_list_free (clist->undo_selection);
-      g_list_free (clist->undo_unselection);
-      clist->undo_selection = NULL;
-      clist->undo_unselection = NULL;
-         
-      if (clist->rows &&
-         ((GtkCListRow *) (clist->row_list->data))->state !=
-         GTK_STATE_SELECTED)
-       fake_toggle_row (clist, 0);
-
-      clist->anchor_state =  GTK_STATE_SELECTED;
-      clist->anchor = 0;
-      clist->drag_pos = 0;
-      clist->undo_anchor = clist->focus_row;
-      update_extended_selection (clist, clist->rows);
-      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
-      return;
-
-    case GTK_SELECTION_MULTIPLE:
-      for (i = 0, list = clist->row_list; list; i++, list = list->next)
-       {
-         if (((GtkCListRow *)(list->data))->state == GTK_STATE_NORMAL)
-           gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
-                            i, -1, NULL);
-       }
-      return;
-    }
+  clist->compare = (cmp_func) ? cmp_func : default_compare;
 }
 
-static void
-fake_unselect_all (GtkCList * clist,
-                  gint       row)
+void       
+gtk_clist_set_auto_sort (GtkCList *clist,
+                        gboolean  auto_sort)
 {
-  GList *list;
-  GList *work;
-  gint i;
-
-  if (row >= 0 && (work = g_list_nth (clist->row_list, row)))
-    {
-      if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
-         GTK_CLIST_ROW (work)->selectable)
-       {
-         GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
-         
-         if (!GTK_CLIST_FROZEN (clist) &&
-             gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-           GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
-                                                 GTK_CLIST_ROW (work));
-       }  
-    }
-
-  clist->undo_selection = clist->selection;
-  clist->selection = NULL;
-  clist->selection_end = NULL;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
   
-  for (list = clist->undo_selection; list; list = list->next)
+  if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort)
+    GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
+  else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort)
     {
-      if ((i = GPOINTER_TO_INT (list->data)) == row ||
-         !(work = g_list_nth (clist->row_list, i)))
-       continue;
-
-      GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
-      if (!GTK_CLIST_FROZEN (clist) &&
-         gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, i,
-                                             GTK_CLIST_ROW (work));
+      GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
+      gtk_clist_sort (clist);
     }
 }
 
-static void
-fake_toggle_row (GtkCList *clist,
-                gint      row)
+void       
+gtk_clist_set_sort_type (GtkCList    *clist,
+                        GtkSortType  sort_type)
 {
-  GList *work;
-
-  if (!(work = g_list_nth (clist->row_list, row))||
-      !GTK_CLIST_ROW (work)->selectable)
-    return;
-  
-  if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
-    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
-  else
-    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
   
-  if (!GTK_CLIST_FROZEN (clist) &&
-      gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-    GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row,
-                                         GTK_CLIST_ROW (work));
+  clist->sort_type = sort_type;
 }
 
-static GList *
-selection_find (GtkCList *clist,
-               gint      row_number,
-               GList    *row_list_element)
+void
+gtk_clist_set_sort_column (GtkCList *clist,
+                          gint      column)
 {
-  return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CLIST (clist));
+
+  if (column < 0 || column >= clist->columns)
+    return;
+
+  clist->sort_column = column;
 }
 
+/* PRIVATE SORTING FUNCTIONS
+ *   default_compare
+ *   real_sort_list
+ *   gtk_clist_merge
+ *   gtk_clist_mergesort
+ */
 static gint
-default_compare (GtkCList     *clist,
-                gconstpointer ptr1,
-                gconstpointer ptr2)
+default_compare (GtkCList      *clist,
+                gconstpointer  ptr1,
+                gconstpointer  ptr2)
 {
   char *text1 = NULL;
   char *text2 = NULL;
@@ -6402,56 +6875,59 @@ default_compare (GtkCList     *clist,
   if (!text1)
     return -1;
 
-  return strcmp (text1, text2);
-}
-
-void
-gtk_clist_set_compare_func (GtkCList            *clist,
-                           GtkCListCompareFunc  cmp_func)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  clist->compare = (cmp_func) ? cmp_func : default_compare;
+  return strcmp (text1, text2);
 }
 
-void       
-gtk_clist_set_auto_sort (GtkCList *clist,
-                        gboolean  auto_sort)
+static void
+real_sort_list (GtkCList *clist)
 {
+  GList *list;
+  GList *work;
+  gint i;
+  gboolean thaw = FALSE;
+
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CLIST (clist));
-  
-  if (GTK_CLIST_AUTO_SORT (clist) && !auto_sort)
-    GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
-  else if (!GTK_CLIST_AUTO_SORT (clist) && auto_sort)
+
+  if (clist->rows <= 1)
+    return;
+
+  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
+    return;
+
+  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
     {
-      GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
-      gtk_clist_sort (clist);
+      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
+      g_list_free (clist->undo_selection);
+      g_list_free (clist->undo_unselection);
+      clist->undo_selection = NULL;
+      clist->undo_unselection = NULL;
+    }
+   
+  if (!GTK_CLIST_FROZEN (clist))
+    {
+      gtk_clist_freeze (clist);
+      thaw = TRUE;
     }
-}
 
-void       
-gtk_clist_set_sort_type (GtkCList   *clist,
-                        GtkSortType sort_type)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-  
-  clist->sort_type = sort_type;
-}
+  clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
 
-void
-gtk_clist_set_sort_column (GtkCList *clist,
-                          gint      column)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
+  work = clist->selection;
 
-  if (column < 0 || column >= clist->columns)
-    return;
+  for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
+    {
+      if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
+       {
+         work->data = GINT_TO_POINTER (i);
+         work = work->next;
+       }
+      
+      if (i == clist->rows - 1)
+       clist->row_list_end = list;
+    }
 
-  clist->sort_column = column;
+  if (thaw)
+    gtk_clist_thaw (clist);
 }
 
 static GList *
@@ -6537,195 +7013,3 @@ gtk_clist_mergesort (GtkCList *clist,
                       gtk_clist_mergesort (clist, half, num - num / 2));
     }
 }
-
-void
-gtk_clist_sort (GtkCList *clist)
-{
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  GTK_CLIST_CLASS_FW (clist)->sort_list (clist);
-}
-
-static void
-real_sort_list (GtkCList *clist)
-{
-  GList *list;
-  GList *work;
-  gint i;
-  gboolean thaw = FALSE;
-
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (clist->rows <= 1)
-    return;
-
-  if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (clist))
-    return;
-
-  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_EXTENDED)
-    {
-      GTK_CLIST_CLASS_FW (clist)->resync_selection (clist, NULL);
-      g_list_free (clist->undo_selection);
-      g_list_free (clist->undo_unselection);
-      clist->undo_selection = NULL;
-      clist->undo_unselection = NULL;
-    }
-   
-  if (!GTK_CLIST_FROZEN (clist))
-    {
-      gtk_clist_freeze (clist);
-      thaw = TRUE;
-    }
-
-  clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
-
-  work = clist->selection;
-
-  for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
-    {
-      if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
-       {
-         work->data = GINT_TO_POINTER (i);
-         work = work->next;
-       }
-      
-      if (i == clist->rows - 1)
-       clist->row_list_end = list;
-    }
-
-  if (thaw)
-    gtk_clist_thaw (clist);
-}
-
-/* gtk_clist_set_cell_style
- * gtk_clist_get_cell_style
- * gtk_clist_set_row_style
- * gtk_clist_get_row_style
- */
-
-void
-gtk_clist_set_cell_style (GtkCList *clist,
-                         gint      row,
-                         gint      column,
-                         GtkStyle *style)
-{
-  GtkCListRow *clist_row;
-
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
-    return;
-
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  if (clist_row->cell[column].style == style)
-    return;
-
-  if (clist_row->cell[column].style)
-    {
-      if (GTK_WIDGET_REALIZED (clist))
-        gtk_style_detach (clist_row->cell[column].style);
-      gtk_style_unref (clist_row->cell[column].style);
-    }
-
-  clist_row->cell[column].style = style;
-
-  if (clist_row->cell[column].style)
-    {
-      gtk_style_ref (clist_row->cell[column].style);
-      
-      if (GTK_WIDGET_REALIZED (clist))
-        clist_row->cell[column].style =
-         gtk_style_attach (clist_row->cell[column].style,
-                           clist->clist_window);
-    }
-
-  /* redraw the list if it's not frozen */
-  if (!GTK_CLIST_FROZEN (clist))
-    {
-      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
-    }
-}
-
-GtkStyle *
-gtk_clist_get_cell_style (GtkCList *clist,
-                         gint      row,
-                         gint      column)
-{
-  GtkCListRow *clist_row;
-
-  g_return_val_if_fail (clist != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
-
-  if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
-    return NULL;
-
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  return clist_row->cell[column].style;
-}
-
-void
-gtk_clist_set_row_style (GtkCList *clist,
-                        gint      row,
-                        GtkStyle *style)
-{
-  GtkCListRow *clist_row;
-
-  g_return_if_fail (clist != NULL);
-  g_return_if_fail (GTK_IS_CLIST (clist));
-
-  if (row < 0 || row >= clist->rows)
-    return;
-
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  if (clist_row->style == style)
-    return;
-
-  if (clist_row->style)
-    {
-      if (GTK_WIDGET_REALIZED (clist))
-        gtk_style_detach (clist_row->style);
-      gtk_style_unref (clist_row->style);
-    }
-
-  clist_row->style = style;
-
-  if (clist_row->style)
-    {
-      gtk_style_ref (clist_row->style);
-      
-      if (GTK_WIDGET_REALIZED (clist))
-        clist_row->style = gtk_style_attach (clist_row->style,
-                                            clist->clist_window);
-    }
-
-  /* redraw the list if it's not frozen */
-  if (!GTK_CLIST_FROZEN (clist))
-    {
-      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
-       GTK_CLIST_CLASS_FW (clist)->draw_row (clist, NULL, row, clist_row);
-    }
-}
-
-GtkStyle *
-gtk_clist_get_row_style (GtkCList *clist,
-                        gint      row)
-{
-  GtkCListRow *clist_row;
-
-  g_return_val_if_fail (clist != NULL, NULL);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
-
-  if (row < 0 || row >= clist->rows)
-    return NULL;
-
-  clist_row = (g_list_nth (clist->row_list, row))->data;
-
-  return clist_row->style;
-}
index 0e56a7892322302180822951a1a2c0b8d9eadb9b..bbc23c762d0f3770a19a9e30e7c12c0c73c400f4 100644 (file)
@@ -36,15 +36,16 @@ extern "C" {
 /* clist flags */
 enum                    
 {
-  GTK_CLIST_FROZEN          = 1 << 0,                                     
-  GTK_CLIST_IN_DRAG         = 1 << 1,                                        
-  GTK_CLIST_DRAG_SELECTION  = 1 << 2,
-  GTK_CLIST_ROW_HEIGHT_SET  = 1 << 3,
-  GTK_CLIST_SHOW_TITLES     = 1 << 4,
-  GTK_CLIST_CONSTRUCTED            = 1 << 5,
-  GTK_CLIST_CHILD_HAS_FOCUS = 1 << 6,
-  GTK_CLIST_ADD_MODE        = 1 << 7,
-  GTK_CLIST_AUTO_SORT       = 1 << 8
+  GTK_CLIST_FROZEN              = 1 << 0,
+  GTK_CLIST_IN_DRAG             = 1 << 1,
+  GTK_CLIST_DRAG_SELECTION      = 1 << 2,
+  GTK_CLIST_ROW_HEIGHT_SET      = 1 << 3,
+  GTK_CLIST_SHOW_TITLES         = 1 << 4,
+  GTK_CLIST_CONSTRUCTED                = 1 << 5,
+  GTK_CLIST_CHILD_HAS_FOCUS     = 1 << 6,
+  GTK_CLIST_ADD_MODE            = 1 << 7,
+  GTK_CLIST_AUTO_SORT           = 1 << 8,
+  GTK_CLIST_AUTO_RESIZE_BLOCKED = 1 << 9
 }; 
 
 /* cell types */
@@ -76,6 +77,7 @@ typedef enum
 #define GTK_CLIST_DRAG_SELECTION(clist)    (GTK_CLIST_FLAGS (clist) & GTK_CLIST_DRAG_SELECTION)
 #define GTK_CLIST_ADD_MODE(clist)          (GTK_CLIST_FLAGS (clist) & GTK_CLIST_ADD_MODE)
 #define GTK_CLIST_AUTO_SORT(clist)         (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_SORT)
+#define GTK_CLIST_AUTO_RESIZE_BLOCKED(clist) (GTK_CLIST_FLAGS (clist) & GTK_CLIST_AUTO_RESIZE_BLOCKED)
 
 #define GTK_CLIST_ROW(_glist_) ((GtkCListRow *)((_glist_)->data))
 
@@ -191,64 +193,68 @@ struct _GtkCListClass
 {
   GtkContainerClass parent_class;
   
-  void   (*select_row)          (GtkCList      *clist,
-                                gint           row,
-                                gint           column,
-                                GdkEvent      *event);
-  void   (*unselect_row)        (GtkCList      *clist,
-                                gint           row,
-                                gint           column,
-                                GdkEvent      *event);
-  void   (*click_column)        (GtkCList      *clist,
-                                gint           column);
-  void   (*resize_column)       (GtkCList      *clist,
-                                gint           column,
-                                 gint           width);
-  void   (*toggle_focus_row)    (GtkCList      *clist);
-  void   (*select_all)          (GtkCList      *clist);
-  void   (*unselect_all)        (GtkCList      *clist);
-  void   (*undo_selection)      (GtkCList      *clist);
-  void   (*start_selection)     (GtkCList      *clist);
-  void   (*end_selection)       (GtkCList      *clist);
-  void   (*extend_selection)    (GtkCList      *clist,
-                                GtkScrollType  scroll_type,
-                                gfloat         position,
-                                gboolean       auto_start_selection);
-  void   (*scroll_horizontal)   (GtkCList      *clist,
-                                GtkScrollType  scroll_type,
-                                gfloat         position);
-  void   (*scroll_vertical)     (GtkCList      *clist,
-                                GtkScrollType  scroll_type,
-                                gfloat         position);
-  void   (*toggle_add_mode)     (GtkCList      *clist);
-  void   (*abort_column_resize) (GtkCList      *clist);
-  void   (*resync_selection)    (GtkCList      *clist,
-                                GdkEvent      *event);
-  GList* (*selection_find)      (GtkCList      *clist,
-                                gint           row_number,
-                                GList         *row_list_element);
-  void   (*draw_row)            (GtkCList      *clist,
-                                GdkRectangle  *area,
-                                gint           row,
-                                GtkCListRow   *clist_row);
-  void   (*clear)               (GtkCList      *clist);
-  void   (*fake_unselect_all)   (GtkCList      *clist,
-                                gint           row);
-  void   (*sort_list)           (GtkCList      *clist);
-  gint   (*insert_row)          (GtkCList      *clist,
-                                gint           row,
-                                gchar         *text[]);
-  void   (*remove_row)          (GtkCList      *clist,
-                                gint           row);
-  void   (*set_cell_contents)   (GtkCList      *clist,
-                                GtkCListRow   *clist_row,
-                                gint           column,
-                                GtkCellType    type,
-                                const gchar   *text,
-                                guint8         spacing,
-                                GdkPixmap     *pixmap,
-                                GdkBitmap     *mask);
-  
+  void   (*select_row)          (GtkCList       *clist,
+                                gint            row,
+                                gint            column,
+                                GdkEvent       *event);
+  void   (*unselect_row)        (GtkCList       *clist,
+                                gint            row,
+                                gint            column,
+                                GdkEvent       *event);
+  void   (*click_column)        (GtkCList       *clist,
+                                gint            column);
+  void   (*resize_column)       (GtkCList       *clist,
+                                gint            column,
+                                 gint            width);
+  void   (*toggle_focus_row)    (GtkCList       *clist);
+  void   (*select_all)          (GtkCList       *clist);
+  void   (*unselect_all)        (GtkCList       *clist);
+  void   (*undo_selection)      (GtkCList       *clist);
+  void   (*start_selection)     (GtkCList       *clist);
+  void   (*end_selection)       (GtkCList       *clist);
+  void   (*extend_selection)    (GtkCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position,
+                                gboolean        auto_start_selection);
+  void   (*scroll_horizontal)   (GtkCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position);
+  void   (*scroll_vertical)     (GtkCList       *clist,
+                                GtkScrollType   scroll_type,
+                                gfloat          position);
+  void   (*toggle_add_mode)     (GtkCList       *clist);
+  void   (*abort_column_resize) (GtkCList       *clist);
+  void   (*resync_selection)    (GtkCList       *clist,
+                                GdkEvent       *event);
+  GList* (*selection_find)      (GtkCList       *clist,
+                                gint            row_number,
+                                GList          *row_list_element);
+  void   (*draw_row)            (GtkCList       *clist,
+                                GdkRectangle   *area,
+                                gint            row,
+                                GtkCListRow    *clist_row);
+  void   (*clear)               (GtkCList       *clist);
+  void   (*fake_unselect_all)   (GtkCList       *clist,
+                                gint            row);
+  void   (*sort_list)           (GtkCList       *clist);
+  gint   (*insert_row)          (GtkCList       *clist,
+                                gint            row,
+                                gchar          *text[]);
+  void   (*remove_row)          (GtkCList       *clist,
+                                gint            row);
+  void   (*set_cell_contents)   (GtkCList       *clist,
+                                GtkCListRow    *clist_row,
+                                gint            column,
+                                GtkCellType     type,
+                                const gchar    *text,
+                                guint8          spacing,
+                                GdkPixmap      *pixmap,
+                                GdkBitmap      *mask);
+  void   (*cell_size_request)   (GtkCList       *clist,
+                                GtkCListRow    *clist_row,
+                                gint            column,
+                                GtkRequisition *requisition);
+
   gint scrollbar_spacing;
 };
 
@@ -265,9 +271,10 @@ struct _GtkCListColumn
   gint max_width;
   GtkJustification justification;
   
-  gint visible    : 1;  
-  gint width_set  : 1;
-  gint resizeable : 1;
+  guint visible     : 1;  
+  guint width_set   : 1;
+  guint resizeable  : 1;
+  guint auto_resize : 1;
 };
 
 struct _GtkCListRow
@@ -283,9 +290,9 @@ struct _GtkCListRow
   gpointer data;
   GtkDestroyNotify destroy;
   
-  gint fg_set     : 1;
-  gint bg_set     : 1;
-  gint selectable : 1;
+  guint fg_set     : 1;
+  guint bg_set     : 1;
+  guint selectable : 1;
 };
 
 /* Cell Structures */
@@ -381,10 +388,14 @@ GtkWidget *gtk_clist_new             (gint   columns);
 GtkWidget *gtk_clist_new_with_titles (gint   columns,
                                      gchar *titles[]);
 
-/* set the border style of the clist */
+/* deprecated function, use gtk_clist_set_shadow_type instead. */
 void gtk_clist_set_border (GtkCList      *clist,
                           GtkShadowType  border);
 
+/* set the border style of the clist */
+void gtk_clist_set_shadow_type (GtkCList      *clist,
+                               GtkShadowType  type);
+
 /* set the clist's selection mode */
 void gtk_clist_set_selection_mode (GtkCList         *clist,
                                   GtkSelectionMode  mode);
@@ -444,6 +455,15 @@ void gtk_clist_set_column_resizeable (GtkCList *clist,
                                      gint      column,
                                      gboolean  resizeable);
 
+/* resize column automatically to its optimal width */
+void gtk_clist_set_column_auto_resize (GtkCList *clist,
+                                      gint      column,
+                                      gboolean  auto_resize);
+
+/* return the optimal column width, i.e. maximum of all cell widths */
+gint gtk_clist_optimal_column_width (GtkCList *clist,
+                                    gint      column);
+
 /* set the pixel width of a column; this is a necessary step in
  * creating a CList because otherwise the column width is chozen from
  * the width of the column title, which will never be right
@@ -546,20 +566,20 @@ void gtk_clist_set_background (GtkCList *clist,
 
 /* set / get cell styles */
 void gtk_clist_set_cell_style (GtkCList *clist,
-                              gint row,
-                              gint column,
+                              gint      row,
+                              gint      column,
                               GtkStyle *style);
 
 GtkStyle *gtk_clist_get_cell_style (GtkCList *clist,
-                                   gint row,
-                                   gint column);
+                                   gint      row,
+                                   gint      column);
 
 void gtk_clist_set_row_style (GtkCList *clist,
-                             gint row,
+                             gint      row,
                              GtkStyle *style);
 
 GtkStyle *gtk_clist_get_row_style (GtkCList *clist,
-                                  gint row);
+                                  gint      row);
 
 /* this sets a horizontal and vertical shift for drawing
  * the contents of a cell; it can be positive or negitive;
index 5ad5744dad762e39f049e2fe12b21b76db99ad4a..a3799e5c87cb5ad43580519ae1cc66d9a4f7d544 100644 (file)
@@ -221,7 +221,14 @@ static void real_sort_list              (GtkCList      *clist);
 static void set_mouse_cursor           (GtkCTree       *ctree,
                                         gboolean       enable);
 static void check_cursor               (GtkCTree       *ctree);
-
+static void cell_size_request           (GtkCList       *clist,
+                                        GtkCListRow    *clist_row,
+                                        gint            column,
+                                        GtkRequisition *requisition);
+static void column_auto_resize          (GtkCList       *clist,
+                                        GtkCListRow    *clist_row,
+                                        gint            column,
+                                        gint            old_width);
 
 enum
 {
@@ -369,6 +376,7 @@ gtk_ctree_class_init (GtkCTreeClass *klass)
   clist_class->remove_row = real_remove_row;
   clist_class->sort_list = real_sort_list;
   clist_class->set_cell_contents = set_cell_contents;
+  clist_class->cell_size_request = cell_size_request;
 
   klass->tree_select_row = real_tree_select;
   klass->tree_unselect_row = real_tree_unselect;
@@ -2521,6 +2529,7 @@ real_tree_move (GtkCTree     *ctree,
   GtkCList *clist;
   GtkCTreeNode *work;
   gboolean thaw = FALSE;
+  gboolean visible = FALSE;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (node != NULL);
@@ -2537,6 +2546,8 @@ real_tree_move (GtkCTree     *ctree,
 
   clist = GTK_CLIST (ctree);
 
+  visible = gtk_ctree_is_viewable (ctree, node);
+
   if (clist->selection_mode == GTK_SELECTION_EXTENDED)
     {
       if (clist->anchor != -1)
@@ -2589,6 +2600,13 @@ real_tree_move (GtkCTree     *ctree,
       clist->undo_anchor = clist->focus_row;
     }
 
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      (visible || gtk_ctree_is_viewable (ctree, node)))
+    gtk_clist_set_column_width
+      (clist, ctree->tree_column,
+       gtk_clist_optimal_column_width (clist, ctree->tree_column));
+
   if (thaw)
     gtk_clist_thaw (clist);
 }
@@ -2642,6 +2660,8 @@ real_tree_expand (GtkCTree     *ctree,
 {
   GtkCList *clist;
   GtkCTreeNode *work;
+  GtkRequisition requisition;
+  gboolean visible;
   gint level;
 
   g_return_if_fail (ctree != NULL);
@@ -2658,6 +2678,14 @@ real_tree_expand (GtkCTree     *ctree,
   GTK_CTREE_ROW (node)->expanded = TRUE;
   level = GTK_CTREE_ROW (node)->level;
 
+  visible = gtk_ctree_is_viewable (ctree, node);
+  /* get cell width if tree_column is auto resized */
+  if (visible && clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CLIST_CLASS_FW (clist)->cell_size_request
+      (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+  /* unref/unset closed pixmap */
   if (GTK_CELL_PIXTEXT 
       (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
     {
@@ -2679,6 +2707,7 @@ real_tree_expand (GtkCTree     *ctree,
        }
     }
 
+  /* set/ref opened pixmap */
   if (GTK_CTREE_ROW (node)->pixmap_opened)
     {
       GTK_CELL_PIXTEXT 
@@ -2691,15 +2720,37 @@ real_tree_expand (GtkCTree     *ctree,
          gdk_pixmap_ref (GTK_CTREE_ROW (node)->mask_opened);
     }
 
+
   work = GTK_CTREE_ROW (node)->children;
   if (work)
     {
+      GList *list;
+      gint *cell_width = NULL;
       gint tmp = 0;
       gint row;
-      GList *list;
+      gint i;
       
+      if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+       {
+         cell_width = g_new0 (gint, clist->columns);
+         if (clist->column[ctree->tree_column].auto_resize)
+             cell_width[ctree->tree_column] = requisition.width;
+       }
+
       while (GTK_CTREE_NODE_NEXT (work))
        {
+         if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+           {
+             /* search maximum cell widths of auto_resize columns */
+             for (i = 0; i < clist->columns; i++)
+               if (clist->column[i].auto_resize)
+                 {
+                   GTK_CLIST_CLASS_FW (clist)->cell_size_request
+                     (clist, &GTK_CTREE_ROW (work)->row, i, &requisition);
+                   cell_width[i] = MAX (requisition.width, cell_width[i]);
+                 }
+           }
+
          work = GTK_CTREE_NODE_NEXT (work);
          tmp++;
        }
@@ -2718,16 +2769,29 @@ real_tree_expand (GtkCTree     *ctree,
       list = (GList *)node;
       list->next = (GList *)(GTK_CTREE_ROW (node)->children);
       
-      if (gtk_ctree_is_viewable (ctree, node))
+      if (visible)
        {
+         /* resize auto_resize columns if needed */
+         for (i = 0; i < clist->columns; i++)
+           if (clist->column[i].auto_resize &&
+               cell_width[i] > clist->column[i].width)
+             gtk_clist_set_column_width (clist, i, cell_width[i]);
+         g_free (cell_width);
+
+         /* update focus_row position */
          row = g_list_position (clist->row_list, (GList *)node);
          if (row < clist->focus_row)
            clist->focus_row += tmp + 1;
+
          clist->rows += tmp + 1;
          if (!GTK_CLIST_FROZEN (ctree))
            gtk_clist_thaw (clist);
        }
     }
+  else if (visible && clist->column[ctree->tree_column].auto_resize)
+    /* resize tree_column if needed */
+    column_auto_resize (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column,
+                       requisition.width);
 }
 
 static void 
@@ -2736,12 +2800,15 @@ real_tree_collapse (GtkCTree     *ctree,
 {
   GtkCList *clist;
   GtkCTreeNode *work;
+  GtkRequisition requisition;
+  gboolean visible;
   gint level;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
 
-  if (!node || !GTK_CTREE_ROW (node)->expanded ||GTK_CTREE_ROW (node)->is_leaf)
+  if (!node || !GTK_CTREE_ROW (node)->expanded ||
+      GTK_CTREE_ROW (node)->is_leaf)
     return;
 
   clist = GTK_CLIST (ctree);
@@ -2752,6 +2819,14 @@ real_tree_collapse (GtkCTree     *ctree,
   GTK_CTREE_ROW (node)->expanded = FALSE;
   level = GTK_CTREE_ROW (node)->level;
 
+  visible = gtk_ctree_is_viewable (ctree, node);
+  /* get cell width if tree_column is auto resized */
+  if (visible && clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    GTK_CLIST_CLASS_FW (clist)->cell_size_request
+      (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column, &requisition);
+
+  /* unref/unset opened pixmap */
   if (GTK_CELL_PIXTEXT 
       (GTK_CTREE_ROW (node)->row.cell[ctree->tree_column])->pixmap)
     {
@@ -2773,6 +2848,7 @@ real_tree_collapse (GtkCTree     *ctree,
        }
     }
 
+  /* set/ref closed pixmap */
   if (GTK_CTREE_ROW (node)->pixmap_closed)
     {
       GTK_CELL_PIXTEXT 
@@ -2814,8 +2890,35 @@ real_tree_collapse (GtkCTree     *ctree,
          clist->row_list_end = (GList *)node;
        }
 
-      if (gtk_ctree_is_viewable (ctree, node))
+      if (visible)
        {
+         /* resize auto_resize columns if needed */
+         if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+           {
+             GList *list;
+             gint new_width;
+             gint i;
+
+             for (i = 0; i < clist->columns; i++)
+               if (clist->column[i].auto_resize)
+                 {
+                   /* run a "gtk_clist_optimal_column_width" but break, if
+                    * the column doesn't shrink */
+                   new_width = 0;
+                   for (list = clist->row_list; list; list = list->next)
+                     {
+                       GTK_CLIST_CLASS_FW (clist)->cell_size_request
+                         (clist, GTK_CLIST_ROW (list), i, &requisition);
+                       new_width = MAX (new_width, requisition.width);
+                       if (new_width == clist->column[i].width)
+                         break;
+                     }
+
+                   if (new_width < clist->column[i].width)
+                     gtk_clist_set_column_width (clist, i, new_width);
+                 }
+           }
+
          row = g_list_position (clist->row_list, (GList *)node);
          if (row < clist->focus_row)
            clist->focus_row -= tmp;
@@ -2824,6 +2927,133 @@ real_tree_collapse (GtkCTree     *ctree,
            gtk_clist_thaw (clist);
        }
     }
+  else if (visible && clist->column[ctree->tree_column].auto_resize &&
+          !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    /* resize tree_column if needed */
+    column_auto_resize (clist, &GTK_CTREE_ROW (node)->row, ctree->tree_column,
+                       requisition.width);
+    
+}
+
+static void
+column_auto_resize (GtkCList    *clist,
+                   GtkCListRow *clist_row,
+                   gint         column,
+                   gint         old_width)
+{
+  /* resize column if needed for auto_resize */
+  GtkRequisition requisition;
+
+  if (!clist->column[column].auto_resize ||
+      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    return;
+
+  GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                column, &requisition);
+
+  if (requisition.width > clist->column[column].width)
+    {
+      if (clist->column[column].max_width < 0)
+       gtk_clist_set_column_width (clist, column, requisition.width);
+      else if (clist->column[column].max_width > clist->column[column].width)
+       gtk_clist_set_column_width (clist, column,
+                                   MIN (requisition.width,
+                                        clist->column[column].max_width));
+    }
+  else if (requisition.width < old_width &&
+          old_width == clist->column[column].width)
+    {
+      GList *list;
+      gint new_width = 0;
+
+      /* run a "gtk_clist_optimal_column_width" but break, if
+       * the column doesn't shrink */
+      for (list = clist->row_list; list; list = list->next)
+       {
+         GTK_CLIST_CLASS_FW (clist)->cell_size_request
+           (clist, GTK_CLIST_ROW (list), column, &requisition);
+         new_width = MAX (new_width, requisition.width);
+         if (new_width == clist->column[column].width)
+           break;
+       }
+      if (new_width < clist->column[column].width)
+       gtk_clist_set_column_width
+         (clist, column, MAX (new_width, clist->column[column].min_width));
+    }
+}
+
+static void
+cell_size_request (GtkCList       *clist,
+                  GtkCListRow    *clist_row,
+                  gint            column,
+                  GtkRequisition *requisition)
+{
+  GtkCTree *ctree;
+  GtkStyle *style;
+  gint width;
+  gint height;
+
+  g_return_if_fail (clist != NULL);
+  g_return_if_fail (GTK_IS_CTREE (clist));
+  g_return_if_fail (requisition != NULL);
+
+  ctree = GTK_CTREE (clist);
+
+  get_cell_style (clist, clist_row, GTK_STATE_PRELIGHT, column, &style,
+                 NULL, NULL);
+
+  switch (clist_row->cell[column].type)
+    {
+    case GTK_CELL_TEXT:
+      requisition->width =
+       gdk_string_width (style->font,
+                         GTK_CELL_TEXT (clist_row->cell[column])->text);
+      requisition->height = style->font->ascent + style->font->descent;
+      break;
+    case GTK_CELL_PIXTEXT:
+      gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width = width +
+       GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing +
+       gdk_string_width (style->font,
+                         GTK_CELL_TEXT (clist_row->cell[column])->text);
+
+      requisition->height = MAX (style->font->ascent + style->font->descent,
+                                height);
+      if (column == ctree->tree_column)
+       {
+         requisition->width += (ctree->tree_spacing + ctree->tree_indent *
+                                (((GtkCTreeRow *) clist_row)->level - 1));
+         switch (ctree->expander_style)
+           {
+           case GTK_CTREE_EXPANDER_NONE:
+             break;
+           case GTK_CTREE_EXPANDER_TRIANGLE:
+             requisition->width += PM_SIZE + 3;
+             break;
+           case GTK_CTREE_EXPANDER_SQUARE:
+           case GTK_CTREE_EXPANDER_CIRCULAR:
+             requisition->width += PM_SIZE + 1;
+             break;
+           }
+         if (ctree->line_style == GTK_CTREE_LINES_TABBED)
+           requisition->width += 3;
+       }
+      break;
+    case GTK_CELL_PIXMAP:
+      gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
+                          &width, &height);
+      requisition->width = width;
+      requisition->height = height;
+      break;
+    default:
+      requisition->width  = 0;
+      requisition->height = 0;
+      break;
+    }
+
+  requisition->width  += clist_row->cell[column].horizontal;
+  requisition->height += clist_row->cell[column].vertical;
 }
 
 static void
@@ -2836,7 +3066,9 @@ set_cell_contents (GtkCList    *clist,
                   GdkPixmap   *pixmap,
                   GdkBitmap   *mask)
 {
+  gboolean visible = FALSE;
   GtkCTree *ctree;
+  GtkRequisition requisition;
 
   g_return_if_fail (clist != NULL);
   g_return_if_fail (GTK_IS_CTREE (clist));
@@ -2844,6 +3076,21 @@ set_cell_contents (GtkCList    *clist,
 
   ctree = GTK_CTREE (clist);
 
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      GtkCTreeNode *parent;
+
+      parent = ((GtkCTreeRow *)clist_row)->parent;
+      if (!parent || (parent && GTK_CTREE_ROW (parent)->expanded &&
+                     gtk_ctree_is_viewable (ctree, parent)))
+       {
+         visible = TRUE;
+         GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist, clist_row,
+                                                        column, &requisition);
+       }
+    }
+
   switch (clist_row->cell[column].type)
     {
     case GTK_CELL_EMPTY:
@@ -2852,13 +3099,11 @@ set_cell_contents (GtkCList    *clist,
     case GTK_CELL_TEXT:
       g_free (GTK_CELL_TEXT (clist_row->cell[column])->text);
       break;
-      
     case GTK_CELL_PIXMAP:
       gdk_pixmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap);
       if (GTK_CELL_PIXMAP (clist_row->cell[column])->mask)
        gdk_bitmap_unref (GTK_CELL_PIXMAP (clist_row->cell[column])->mask);
       break;
-      
     case GTK_CELL_PIXTEXT:
       if (GTK_CELL_PIXTEXT (clist_row->cell[column])->text)
        g_free (GTK_CELL_PIXTEXT (clist_row->cell[column])->text);
@@ -2871,7 +3116,6 @@ set_cell_contents (GtkCList    *clist,
              (GTK_CELL_PIXTEXT (clist_row->cell[column])->mask);
        }
       break;
-
     case GTK_CELL_WIDGET:
       /* unimplimented */
       break;
@@ -2893,7 +3137,6 @@ set_cell_contents (GtkCList    *clist,
          GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
        }
       break;
-
     case GTK_CELL_PIXMAP:
       if (pixmap)
        {
@@ -2903,7 +3146,6 @@ set_cell_contents (GtkCList    *clist,
          GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
        }
       break;
-
     case GTK_CELL_PIXTEXT:
       if (column == ctree->tree_column)
        {
@@ -2933,10 +3175,12 @@ set_cell_contents (GtkCList    *clist,
          GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
        }
       break;
-
     default:
       break;
     }
+  
+  if (visible)
+    column_auto_resize (clist, clist_row, column, requisition.width);
 }
 
 static void 
@@ -3654,6 +3898,22 @@ gtk_ctree_insert_node (GtkCTree     *ctree,
 
   gtk_ctree_link (ctree, node, parent, sibling, TRUE);
 
+  if (text && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist) &&
+      gtk_ctree_is_viewable (ctree, node))
+    {
+      GtkRequisition requisition;
+
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           GTK_CLIST_CLASS_FW (clist)->cell_size_request (clist,
+                                                          &(new_row->row),
+                                                          i, &requisition);
+           if (requisition.width > clist->column[i].width)
+             gtk_clist_set_column_width (clist, i, requisition.width);
+         }
+    }
+
   if (!GTK_CLIST_FROZEN (clist))
     gtk_clist_thaw (clist);
 
@@ -3816,9 +4076,40 @@ gtk_ctree_remove_node (GtkCTree     *ctree,
 
   if (node)
     {
+      gboolean visible;
+
+      visible = gtk_ctree_is_viewable (ctree, node);
       gtk_ctree_unlink (ctree, node, TRUE);
       gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_delete),
                                NULL);
+
+      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+       {
+         GtkRequisition requisition;
+         GList *list;
+         gint new_width;
+         gint i;
+
+         for (i = 0; i < clist->columns; i++)
+           if (clist->column[i].auto_resize)
+             {
+               /* run a "gtk_clist_optimal_column_width" but break, if
+                * the column doesn't shrink */
+               new_width = 0;
+               for (list = clist->row_list; list; list = list->next)
+                 {
+                   GTK_CLIST_CLASS_FW (clist)->cell_size_request
+                     (clist, GTK_CLIST_ROW (list), i, &requisition);
+                   new_width = MAX (new_width, requisition.width);
+                   if (new_width == clist->column[i].width)
+                     break;
+                 }
+
+               if (new_width < clist->column[i].width)
+                 gtk_clist_set_column_width (clist, i, new_width);
+             }
+       }
+
     }
   else
     gtk_clist_clear (clist);
@@ -3846,11 +4137,12 @@ real_clear (GtkCList *clist)
   ctree->drag_target    = NULL;
   ctree->drag_icon      = NULL;
 
-  /* remove all the rows */
+  /* remove all rows */
   work = GTK_CTREE_NODE (clist->row_list);
   clist->row_list = NULL;
   clist->row_list_end = NULL;
 
+  GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
   while (work)
     {
       ptr = work;
@@ -3858,6 +4150,7 @@ real_clear (GtkCList *clist)
       gtk_ctree_post_recursive (ctree, ptr, GTK_CTREE_FUNC (tree_delete_row), 
                                NULL);
     }
+  GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
 
   (parent_class->clear) (clist);
 }
@@ -4353,6 +4646,7 @@ gtk_ctree_collapse_recursive (GtkCTree     *ctree,
 {
   GtkCList *clist;
   gboolean thaw = FALSE;
+  gint i;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
@@ -4369,7 +4663,13 @@ gtk_ctree_collapse_recursive (GtkCTree     *ctree,
       thaw = TRUE;
     }
 
+  GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
   gtk_ctree_post_recursive (ctree, node, GTK_CTREE_FUNC (tree_collapse), NULL);
+  GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize)
+      gtk_clist_set_column_width (clist, i,
+                                 gtk_clist_optimal_column_width (clist, i));
 
   if (thaw)
     gtk_clist_thaw (clist);
@@ -4382,6 +4682,7 @@ gtk_ctree_collapse_to_depth (GtkCTree     *ctree,
 {
   GtkCList *clist;
   gboolean thaw = FALSE;
+  gint i;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
@@ -4398,9 +4699,15 @@ gtk_ctree_collapse_to_depth (GtkCTree     *ctree,
       thaw = TRUE;
     }
 
+  GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
   gtk_ctree_post_recursive_to_depth (ctree, node, depth,
                                     GTK_CTREE_FUNC (tree_collapse_to_depth),
                                     GINT_TO_POINTER (depth));
+  GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
+  for (i = 0; i < clist->columns; i++)
+    if (clist->column[i].auto_resize)
+      gtk_clist_set_column_width (clist, i,
+                                 gtk_clist_optimal_column_width (clist, i));
 
   if (thaw)
     gtk_clist_thaw (clist);
@@ -4691,6 +4998,10 @@ gtk_ctree_node_set_shift (GtkCTree     *ctree,
                          gint          vertical,
                          gint          horizontal)
 {
+  GtkCList *clist;
+  GtkRequisition requisition;
+  gboolean visible = FALSE;
+
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
   g_return_if_fail (node != NULL);
@@ -4698,9 +5009,24 @@ gtk_ctree_node_set_shift (GtkCTree     *ctree,
   if (column < 0 || column >= GTK_CLIST (ctree)->columns)
     return;
 
+  clist = GTK_CLIST (ctree);
+
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      visible = gtk_ctree_is_viewable (ctree, node);
+      if (visible)
+       GTK_CLIST_CLASS_FW (clist)->cell_size_request
+         (clist, &GTK_CTREE_ROW (node)->row, column, &requisition);
+    }
+
   GTK_CTREE_ROW (node)->row.cell[column].vertical   = vertical;
   GTK_CTREE_ROW (node)->row.cell[column].horizontal = horizontal;
 
+  if (visible)
+    column_auto_resize (clist, &GTK_CTREE_ROW (node)->row,
+                       column, requisition.width);
+
   tree_draw_node (ctree, node);
 }
 
@@ -4898,6 +5224,8 @@ gtk_ctree_node_set_cell_style (GtkCTree     *ctree,
                               GtkStyle     *style)
 {
   GtkCList *clist;
+  GtkRequisition requisition;
+  gboolean visible = FALSE;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
@@ -4911,6 +5239,15 @@ gtk_ctree_node_set_cell_style (GtkCTree     *ctree,
   if (GTK_CTREE_ROW (node)->row.cell[column].style == style)
     return;
 
+  if (clist->column[column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      visible = gtk_ctree_is_viewable (ctree, node);
+      if (visible)
+       GTK_CLIST_CLASS_FW (clist)->cell_size_request
+         (clist, &GTK_CTREE_ROW (node)->row, column, &requisition);
+    }
+
   if (GTK_CTREE_ROW (node)->row.cell[column].style)
     {
       if (GTK_WIDGET_REALIZED (ctree))
@@ -4930,6 +5267,10 @@ gtk_ctree_node_set_cell_style (GtkCTree     *ctree,
                            clist->clist_window);
     }
 
+  if (visible)
+    column_auto_resize (clist, &GTK_CTREE_ROW (node)->row, column,
+                       requisition.width);
+
   tree_draw_node (ctree, node);
 }
 
@@ -4954,6 +5295,10 @@ gtk_ctree_node_set_row_style (GtkCTree     *ctree,
                              GtkStyle     *style)
 {
   GtkCList *clist;
+  GtkRequisition requisition;
+  gboolean visible;
+  gint *old_width = NULL;
+  gint i;
 
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
@@ -4963,6 +5308,19 @@ gtk_ctree_node_set_row_style (GtkCTree     *ctree,
 
   if (GTK_CTREE_ROW (node)->row.style == style)
     return;
+  
+  visible = gtk_ctree_is_viewable (ctree, node);
+  if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      old_width = g_new (gint, clist->columns);
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         {
+           GTK_CLIST_CLASS_FW (clist)->cell_size_request
+             (clist, &GTK_CTREE_ROW (node)->row, i, &requisition);
+           old_width[i] = requisition.width;
+         }
+    }
 
   if (GTK_CTREE_ROW (node)->row.style)
     {
@@ -4983,6 +5341,14 @@ gtk_ctree_node_set_row_style (GtkCTree     *ctree,
                            clist->clist_window);
     }
 
+  if (visible && !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      for (i = 0; i < clist->columns; i++)
+       if (clist->column[i].auto_resize)
+         column_auto_resize (clist, &GTK_CTREE_ROW (node)->row, i,
+                             old_width[i]);
+      g_free (old_width);
+    }
   tree_draw_node (ctree, node);
 }
 
@@ -5115,37 +5481,57 @@ GtkVisibility gtk_ctree_node_is_visible (GtkCTree     *ctree,
  *             GtkCTree specific functions                 *
  ***********************************************************/
 
-
 void
 gtk_ctree_set_indent (GtkCTree *ctree, 
                       gint      indent)
 {
+  GtkCList *clist;
+
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
   g_return_if_fail (indent >= 0);
 
-  if (indent != ctree->tree_indent)
-    {
-      ctree->tree_indent = indent;
-      if (!GTK_CLIST_FROZEN (ctree))
-       gtk_clist_thaw (GTK_CLIST (ctree));
-    }
+  if (indent == ctree->tree_indent)
+    return;
+
+  clist = GTK_CLIST (ctree);
+  ctree->tree_indent = indent;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    gtk_clist_set_column_width
+      (clist, ctree->tree_column,
+       gtk_clist_optimal_column_width (clist, ctree->tree_column));
+  else if (!GTK_CLIST_FROZEN (ctree))
+    gtk_clist_thaw (GTK_CLIST (ctree));
 }
 
 void
 gtk_ctree_set_spacing (GtkCTree *ctree, 
                       gint      spacing)
 {
+  GtkCList *clist;
+  gint old_spacing;
+
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
   g_return_if_fail (spacing >= 0);
 
-  if (spacing != ctree->tree_spacing)
-    {
-      ctree->tree_spacing = spacing;
-      if (!GTK_CLIST_FROZEN (ctree))
-       gtk_clist_thaw (GTK_CLIST (ctree));
-    }
+  if (spacing == ctree->tree_spacing)
+    return;
+
+  clist = GTK_CLIST (ctree);
+
+  old_spacing = ctree->tree_spacing;
+  ctree->tree_spacing = spacing;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    gtk_clist_set_column_width (clist, ctree->tree_column,
+                               clist->column[ctree->tree_column].width +
+                               spacing - old_spacing);
+  else if (!GTK_CLIST_FROZEN (ctree))
+    gtk_clist_thaw (GTK_CLIST (ctree));
 }
 
 void
@@ -5198,16 +5584,35 @@ void
 gtk_ctree_set_line_style (GtkCTree          *ctree, 
                          GtkCTreeLineStyle  line_style)
 {
+  GtkCList *clist;
+  GtkCTreeLineStyle old_style;
+
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
 
-  if (line_style != ctree->line_style)
-    {
-      ctree->line_style = line_style;
+  if (line_style == ctree->line_style)
+    return;
 
-      if (!GTK_WIDGET_REALIZED (ctree))
-       return;
+  clist = GTK_CLIST (ctree);
+
+  old_style = ctree->line_style;
+  ctree->line_style = line_style;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
+    {
+      if (old_style == GTK_CTREE_LINES_TABBED)
+       gtk_clist_set_column_width
+         (clist, ctree->tree_column,
+          clist->column[ctree->tree_column].width - 3);
+      else if (line_style == GTK_CTREE_LINES_TABBED)
+       gtk_clist_set_column_width
+         (clist, ctree->tree_column,
+          clist->column[ctree->tree_column].width + 3);
+    }
 
+  if (GTK_WIDGET_REALIZED (ctree))
+    {
       switch (line_style)
        {
        case GTK_CTREE_LINES_SOLID:
@@ -5240,16 +5645,57 @@ void
 gtk_ctree_set_expander_style (GtkCTree              *ctree, 
                              GtkCTreeExpanderStyle  expander_style)
 {
+  GtkCList *clist;
+  GtkCTreeExpanderStyle old_style;
+
   g_return_if_fail (ctree != NULL);
   g_return_if_fail (GTK_IS_CTREE (ctree));
 
-  if (expander_style != ctree->expander_style)
+  if (expander_style == ctree->expander_style)
+    return;
+
+  clist = GTK_CLIST (ctree);
+
+  old_style = ctree->expander_style;
+  ctree->expander_style = expander_style;
+
+  if (clist->column[ctree->tree_column].auto_resize &&
+      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
     {
-      ctree->expander_style = expander_style;
+      gint new_width;
 
-      if (!GTK_CLIST_FROZEN (ctree))
-       gtk_clist_thaw (GTK_CLIST (ctree));
+      new_width = clist->column[ctree->tree_column].width;
+      switch (old_style)
+       {
+       case GTK_CTREE_EXPANDER_NONE:
+         break;
+       case GTK_CTREE_EXPANDER_TRIANGLE:
+         new_width -= PM_SIZE + 3;
+         break;
+       case GTK_CTREE_EXPANDER_SQUARE:
+       case GTK_CTREE_EXPANDER_CIRCULAR:
+         new_width -= PM_SIZE + 1;
+         break;
+       }
+
+      switch (expander_style)
+       {
+       case GTK_CTREE_EXPANDER_NONE:
+         break;
+       case GTK_CTREE_EXPANDER_TRIANGLE:
+         new_width += PM_SIZE + 3;
+         break;
+       case GTK_CTREE_EXPANDER_SQUARE:
+       case GTK_CTREE_EXPANDER_CIRCULAR:
+         new_width += PM_SIZE + 1;
+         break;
+       }
+
+      gtk_clist_set_column_width (clist, ctree->tree_column, new_width);
     }
+
+  if (!GTK_CLIST_FROZEN (ctree) && GTK_WIDGET_DRAWABLE (clist))
+    gtk_clist_thaw (GTK_CLIST (ctree));
 }
 
 
index 68ff79724daa3d6892784c52de52b8a4bc4c1669..98cb6f20ad41d8aeab8d013abbff8ddf27f1156a 100644 (file)
@@ -3542,7 +3542,7 @@ add1000_clist (GtkWidget *widget, gpointer data)
   gtk_clist_freeze (GTK_CLIST (data));
   for (i = 0; i < 1000; i++)
     {
-      sprintf (text[0], "Row %d", rand() % 10000);
+      sprintf (text[0], "CListRow %d", rand() % 10000);
       row = gtk_clist_append (clist, texts);
       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
     }
@@ -3572,7 +3572,7 @@ add10000_clist (GtkWidget *widget, gpointer data)
   gtk_clist_freeze (GTK_CLIST (data));
   for (i = 0; i < 10000; i++)
     {
-      sprintf (text[0], "Row %d", rand() % 10000 /*clist_rows++*/);
+      sprintf (text[0], "CListRow %d", rand() % 10000);
       gtk_clist_append (GTK_CLIST (data), texts);
     }
   gtk_clist_thaw (GTK_CLIST (data));
@@ -3830,7 +3830,7 @@ clist_toggle_sel_mode (GtkWidget *widget, GtkCList *clist)
 static void 
 clist_click_column (GtkCList *clist, gint column, gpointer data)
 {
-  if (column == 5)
+  if (column == 4)
     gtk_clist_set_column_visibility (clist, column, FALSE);
   else if (column == clist->sort_column)
     {
@@ -3853,8 +3853,8 @@ create_clist (void)
 
   static char *titles[] =
   {
-    "Title 0",  "Title 1",  "not resizeable", "max width 120",
-    "min width 40", "hide column", "Title 6", "Title 7",
+    "auto resize", "not resizeable", "max width 100", "min width 50",
+    "hide column", "Title 5", "Title 6", "Title 7",
     "Title 8",  "Title 9",  "Title 10", "Title 11", "Title 12",
     "Title 13", "Title 14", "Title 15", "Title 16", "Title 17",
     "Title 18", "Title 19"
@@ -4008,9 +4008,10 @@ create_clist (void)
       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
        gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
 
-      gtk_clist_set_column_resizeable (GTK_CLIST (clist), 2, FALSE);
-      gtk_clist_set_column_max_width (GTK_CLIST (clist), 3, 120);
-      gtk_clist_set_column_min_width (GTK_CLIST (clist), 4, 40);
+      gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
+      gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
+      gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
+      gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
 
       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
       gtk_clist_set_policy (GTK_CLIST (clist), GTK_POLICY_AUTOMATIC,
@@ -4047,7 +4048,7 @@ create_clist (void)
 
       for (i = 0; i < 10; i++)
        {
-         sprintf (text[0], "Row %d", clist_rows++);
+         sprintf (text[0], "CListRow %d", clist_rows++);
          gtk_clist_append (GTK_CLIST (clist), texts);
 
          switch (i % 4)
@@ -4832,8 +4833,11 @@ void create_ctree (void)
 
       button = gtk_button_new_with_label ("Rebuild tree");
       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-      
+
       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
+      gtk_signal_connect (GTK_OBJECT (button), "clicked",
+                         GTK_SIGNAL_FUNC (rebuild_tree), ctree);
+      
       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
       line_style = GTK_CTREE_LINES_DOTTED;
 
@@ -4866,12 +4870,10 @@ void create_ctree (void)
       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
       gtk_clist_set_policy (GTK_CLIST (ctree), GTK_POLICY_ALWAYS, 
                            GTK_POLICY_AUTOMATIC);
-      gtk_clist_set_column_width (GTK_CLIST (ctree), 0, 200);
+      gtk_clist_set_column_min_width (GTK_CLIST (ctree), 0, 50);
+      gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
 
-      gtk_signal_connect (GTK_OBJECT (button), "clicked",
-                         GTK_SIGNAL_FUNC (rebuild_tree), ctree);
-      
       bbox = gtk_hbox_new (FALSE, 5);
       gtk_container_border_width (GTK_CONTAINER (bbox), 5);
       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
@@ -6264,7 +6266,7 @@ create_dnd (void)
   else
     gtk_widget_destroy (window);
 }
-#endif 
+#endif
 
 /*
  * Shaped Windows
index 68ff79724daa3d6892784c52de52b8a4bc4c1669..98cb6f20ad41d8aeab8d013abbff8ddf27f1156a 100644 (file)
@@ -3542,7 +3542,7 @@ add1000_clist (GtkWidget *widget, gpointer data)
   gtk_clist_freeze (GTK_CLIST (data));
   for (i = 0; i < 1000; i++)
     {
-      sprintf (text[0], "Row %d", rand() % 10000);
+      sprintf (text[0], "CListRow %d", rand() % 10000);
       row = gtk_clist_append (clist, texts);
       gtk_clist_set_pixtext (clist, row, 3, "gtk+", 5, pixmap, mask);
     }
@@ -3572,7 +3572,7 @@ add10000_clist (GtkWidget *widget, gpointer data)
   gtk_clist_freeze (GTK_CLIST (data));
   for (i = 0; i < 10000; i++)
     {
-      sprintf (text[0], "Row %d", rand() % 10000 /*clist_rows++*/);
+      sprintf (text[0], "CListRow %d", rand() % 10000);
       gtk_clist_append (GTK_CLIST (data), texts);
     }
   gtk_clist_thaw (GTK_CLIST (data));
@@ -3830,7 +3830,7 @@ clist_toggle_sel_mode (GtkWidget *widget, GtkCList *clist)
 static void 
 clist_click_column (GtkCList *clist, gint column, gpointer data)
 {
-  if (column == 5)
+  if (column == 4)
     gtk_clist_set_column_visibility (clist, column, FALSE);
   else if (column == clist->sort_column)
     {
@@ -3853,8 +3853,8 @@ create_clist (void)
 
   static char *titles[] =
   {
-    "Title 0",  "Title 1",  "not resizeable", "max width 120",
-    "min width 40", "hide column", "Title 6", "Title 7",
+    "auto resize", "not resizeable", "max width 100", "min width 50",
+    "hide column", "Title 5", "Title 6", "Title 7",
     "Title 8",  "Title 9",  "Title 10", "Title 11", "Title 12",
     "Title 13", "Title 14", "Title 15", "Title 16", "Title 17",
     "Title 18", "Title 19"
@@ -4008,9 +4008,10 @@ create_clist (void)
       for (i = 1; i < TESTGTK_CLIST_COLUMNS; i++)
        gtk_clist_set_column_width (GTK_CLIST (clist), i, 80);
 
-      gtk_clist_set_column_resizeable (GTK_CLIST (clist), 2, FALSE);
-      gtk_clist_set_column_max_width (GTK_CLIST (clist), 3, 120);
-      gtk_clist_set_column_min_width (GTK_CLIST (clist), 4, 40);
+      gtk_clist_set_column_auto_resize (GTK_CLIST (clist), 0, TRUE);
+      gtk_clist_set_column_resizeable (GTK_CLIST (clist), 1, FALSE);
+      gtk_clist_set_column_max_width (GTK_CLIST (clist), 2, 100);
+      gtk_clist_set_column_min_width (GTK_CLIST (clist), 3, 50);
 
       gtk_clist_set_selection_mode (GTK_CLIST (clist), GTK_SELECTION_EXTENDED);
       gtk_clist_set_policy (GTK_CLIST (clist), GTK_POLICY_AUTOMATIC,
@@ -4047,7 +4048,7 @@ create_clist (void)
 
       for (i = 0; i < 10; i++)
        {
-         sprintf (text[0], "Row %d", clist_rows++);
+         sprintf (text[0], "CListRow %d", clist_rows++);
          gtk_clist_append (GTK_CLIST (clist), texts);
 
          switch (i % 4)
@@ -4832,8 +4833,11 @@ void create_ctree (void)
 
       button = gtk_button_new_with_label ("Rebuild tree");
       gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
-      
+
       ctree = GTK_CTREE (gtk_ctree_new_with_titles (2, 0, title));
+      gtk_signal_connect (GTK_OBJECT (button), "clicked",
+                         GTK_SIGNAL_FUNC (rebuild_tree), ctree);
+      
       gtk_ctree_set_line_style (ctree, GTK_CTREE_LINES_DOTTED);
       line_style = GTK_CTREE_LINES_DOTTED;
 
@@ -4866,12 +4870,10 @@ void create_ctree (void)
       gtk_clist_set_selection_mode (GTK_CLIST (ctree), GTK_SELECTION_EXTENDED);
       gtk_clist_set_policy (GTK_CLIST (ctree), GTK_POLICY_ALWAYS, 
                            GTK_POLICY_AUTOMATIC);
-      gtk_clist_set_column_width (GTK_CLIST (ctree), 0, 200);
+      gtk_clist_set_column_min_width (GTK_CLIST (ctree), 0, 50);
+      gtk_clist_set_column_auto_resize (GTK_CLIST (ctree), 0, TRUE);
       gtk_clist_set_column_width (GTK_CLIST (ctree), 1, 200);
 
-      gtk_signal_connect (GTK_OBJECT (button), "clicked",
-                         GTK_SIGNAL_FUNC (rebuild_tree), ctree);
-      
       bbox = gtk_hbox_new (FALSE, 5);
       gtk_container_border_width (GTK_CONTAINER (bbox), 5);
       gtk_box_pack_start (GTK_BOX (vbox), bbox, FALSE, TRUE, 0);
@@ -6264,7 +6266,7 @@ create_dnd (void)
   else
     gtk_widget_destroy (window);
 }
-#endif 
+#endif
 
 /*
  * Shaped Windows